1. 程式人生 > 其它 >從零開始的python自學之旅(二)

從零開始的python自學之旅(二)

技術標籤:演算法動態規劃leetcodejava資料結構

leetcode-62:不同路徑

一個機器人位於一個 m x n 網格的左上角 (起始點在下圖中標記為“Start” )。 機器人每次只能向下或者向右移動一步。機器人試圖達到網格的右下角(在下圖中標記為“Finish”)。 問總共有多少條不同的路徑? 來源:力扣(LeetCode) 連結:https://leetcode-cn.com/problems/unique-paths 著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

  • dp[i, j] 表示位置(i, j)的路徑數
  • 因為機器人只能向下或右移動,則位置(i, j)可從(i-1, j)或(i, j - 1)到達。則有 dp[i, j] = dp[i-1, j] + dp[i, j-1]。且dp[0, j]和dp[i, 0]都為1
  • 使用dp[i, j] = dp[i-1, j] + dp[i, j-1]求剩下的dp(注意順序性,從左到右,從上到下)
public class Solution {
    public int UniquePaths(int m, int n) {
        int[,] dp = new int[n, m];

        for (int row = 0; row < n; row++)
        {
            for (int column = 0; column < m; column++)
            {
                if (row == 0 || column == 0) { dp[row, column] = 1; }
                else { dp[row, column] = dp[row - 1, column] + dp[row, column - 1]; }
            }
        }

        return dp[n - 1, m - 1];
    }
}

優化1

  • 只需要2行或2列的陣列來儲存dp即可,因為每一行或列的計算只依賴上一行或列的值

優化2

  • 只需要1行或列的陣列來儲存dp即可,因為可以就地儲存
public class Solution {
    public int UniquePaths(int m, int n) {
        // 只需要一維dp陣列儲存即可
        int min = m < n ? m : n;
        int max = m < n ? n : m;
        int[] dp = new int[min];
        for (int i = 0; i < max; i++)
        {
            for (int j = 0; j < min; j++)
            {
                if (i == 0 || j == 0) { dp[j] = 1; }
                else { dp[j] = dp[j - 1] + dp[j]; } 
            }
        }
        return dp[min - 1];
    }
}

leetcode-300:最長上升子序列

給定一個無序的整數陣列,找到其中最長上升子序列的長度。

示例:

輸入: [10,9,2,5,3,7,101,18] 輸出: 4 解釋: 最長的上升子序列是[2,3,7,101],它的長度是 4。 說明:

可能會有多種最長上升子序列的組合,你只需要輸出對應的長度即可。 你演算法的時間複雜度應該為O(n2) 。 進階: 你能將演算法的時間複雜度降低到O(n log n) 嗎?

來源:力扣(LeetCode) 連結:https://leetcode-cn.com/problems/longest-increasing-subsequence 著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

關鍵

  • nums[i]比nums[j]大,說明該元素可以與dp[j]代表的子序列一起組成上升序列(長度為dp[j] + 1)
public class Solution {
    public int LengthOfLIS(int[] nums) {
        if (nums.Length <= 1) { return nums.Length; }
        // dp[i]表示 0~i 之間的上升子序列長度
        int[] dp = new int[nums.Length];
        int max = 1;
        for (int i = 0; i < nums.Length; i++)
        {
            dp[i] = 1;
            for (int j = 0; j < i; j++)
            {
                // 關鍵:nums[i]比nums[j]大,說明該元素可以與dp[j]代表的子序列一起組成上升序列(長度為dp[j] + 1)
                // 如果長度比當前dp[i]大,才更新dp[i]
                if (nums[i] > nums[j] && dp[j] + 1 > dp[i]) 
                { 
                    dp[i] = dp[j] + 1;
                }
            }
            // 如果有更長的上升序列,則更新
            if (dp[i] > max) { max = dp[i]; } 
        }
        return max;
    }
}