有趣的算法02

有趣的算法02

​ 爲提高算法、編程能力,開始刷LeetCode,一些於我有益的題記錄在此係列中(或許對大佬們而言滿是些簡單的題,還請見諒)。同時感謝解體區的大佬們。
Pure mathematics is, in this way, the poetry of logical ideas. -- Einstein

[使數組惟一的最小增量]

【問題描述】

​ 給定一個整數數組,每次move操做能夠數組中任意元素,將其增1。問move操做數最少能夠爲多少,使數組中每一個數都是惟一的,參LeetCode 945. 使數組惟一的最小增量算法

【解法思路】

  1. 先排序,後遍歷:時間複雜度$O(n\log n)$編程

    public int minIncrementForUnique(vector<int>& A) {
      //先排序
        sort(A.begin(), A.end());
      int count = 0;
      
      //再遍歷,若當前元素小於等於前一個,則變爲前一個元素加1
      for(int i=1; i<A.size(); i++){
        if(A[i]<=A[i-1]){
          count += A[i-1]+1-A[i];
          A[i] = A[i-1]+1;
        }
      }
      
      return count;
    }
  2. 計數排序,用空間換時間:時間複雜度$O(n)$數組

    public int minIncrementForUnique(vector<int>& A) {
      int counter[50000] = {0};
      
      //計數
      for(int i=0; i<A.size(); i++){
        counter[A[i]]++;
      }
      int count = 0;
      
      //若是同一個數的數量n大於1,則將n-1個數移入下一個位置
      for(int i=0; i<50000; i++){
        if(counter[i]>1){
          count+=counter[i]-1;
          counter[i+1]+=counter[i]-1;
        }
      }
    
      return count;
    }
  3. 尋找空位,填入數值:時間複雜度$O(n)$

[鏈表的中間節點]--快慢指針

【問題描述】

​ 已知一個非空單鏈表的頭指針head,要求返回鏈表的中間節點(如有兩個中間節點,則返回第二個中間節點),參LeetCode 876. 鏈表的中間結點ide

【解法思路】

  1. 遍歷鏈表獲得長度,找到中間長度,再遍歷獲得。this

    ListNode* middleNode(ListNode* head) {
            int count = 0;
            int runNum = 0;
            ListNode *p = head;
    
            while (p->next != NULL) {
                p = p->next;
                        ++count;
            }
    
            runNum = (count + 1) / 2 + 1;
            p = head;
    
            for (count = 1; count < runNum; ++count) {
                p = p->next;
            }
    
            return p;
        }
  2. 使用快慢指針,快指針一次走兩步,慢指針一次走一步。編碼

    public ListNode* middleNode(ListNode* head) {
      ListNode* fast = head;
      ListNode* slow = head;
      
      while (fast != NULL && fast->next!=NULL) {
        fast = (fast->next)->next;
        slow = slow->next;
      }
      
      return slow;
    }

[打家劫舍]--動態規劃

【問題描述】

​ 給定一個非負整數數組,按序找出一個相鄰兩數在原數組中不相鄰的子序列,求最大和,參LeetCode 198. 打家劫舍idea

【解法思路】

  • 典型的動態規劃問題,每次有偷和不偷兩種選擇,能夠寫出狀態轉移方程:${\rm dp}[i]=\max({\rm dp}[i-1],{\rm dp}[i-2]+{\rm nums}[i])$
  • 編碼實現以下:指針

    public int rob(vector<int>& nums) {
      vector<int> dp(nums.size(),0);
      
      if(nums.size()==0) return 0;
      else if(nums.size()==1) return nums[0];
      
      dp[0] = nums[0];
      dp[1] = max(nums[0],nums[1]);
      for(int i=2; i<nums.size(); i++){
        dp[i] = max(dp[i-1],dp[i-2]+nums[i]);
      }
    
      return dp[nums.size()-1];
    }
繼續,繼續~
相關文章
相關標籤/搜索