2021年3月刷题(上) Unique Paths,Subsets

这篇博客探讨了两个计算机科学问题:机器人在有障碍的网格中找到唯一路径和生成数组的子集。对于第一个问题,给出了从起点到终点的唯一路径数量的计算方法,并提供了处理障碍的解决方案。第二个问题涉及从给定数组生成所有可能的子集,包括具有重复元素的情况。博客通过递归和组合思想来实现这些算法,提供了详细的代码示例。
摘要由CSDN通过智能技术生成

题目都来源于leetcode网站。题目的图片参考原网站绘制。
第一周:
62. Unique Paths

A robot is located at the top-left corner of a m x n grid (marked ‘Start’ in the diagram below).
The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked ‘Finish’ in the diagram below).
How many possible unique paths are there?
Example 1:
参看原始网站绘制

Input: m = 3, n = 7 Output: 28 Example 2: Input: m = 3, n = 2 Output:
3 Explanation: From the top-left corner, there are a total of 3 ways
to reach the bottom-right corner:

  1. Right -> Down -> Down
  2. Down -> Down -> Right
  3. Down -> Right -> Down

Example 3
Input: m = 7, n = 3 Output: 28
Example 4:
Input: m = 3, n =3 Output: 6

这是关于机器人寻找路径的题,机器人从开始位置走到终点,输入为m,n。表示m,n的地图表格,机器人初始位置是(0,0),终点是右下角(m-1,n-1)。机器人每一步只能向下和向右走,输出走到终点的不重复的路径条数。
不管哪条路径,从起点到终点需要:向下(m-1 步)+向右(n-1步)。求解过程自然就和组合联系到一起,返回结果即为:
C m + n − 2 m − 1 或 C m + n − 2 n − 1 C_{m+n-2}^{m-1} 或 C_{m+n-2}^{n-1} Cm+n2m1Cm+n2n1
我直接编写了一个求解组合的函数:

public class Solution {
    public int UniquePaths(int m, int n) {
        return (int)CombinationResult(m+n-2,m-1);
    }
    
    public static Int64 CombinationResult(int m, int n) 
        {
            Int64 result = 1;
            if (m == 0 || n == 0) return result;
            if (n > m / 2) 
            {
                n = m - n;
            }
            for (int i = 0; i < n; i++)
            {
                result = result * (m - i) / (i + 1);
            }
            return result;
        }
}

63. Unique Paths II

A robot is located at the top-left corner of a m x n grid (marked ‘Start’ in the diagram below).
The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked ‘Finish’ in the diagram below).
Now consider if some obstacles are added to the grids. How many unique paths would there be?
An obstacle and space is marked as 1 and 0 respectively in the grid.

Example 1:
Input: obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]]
Output: 2
Explanation: There is one obstacle in the middle of the 3x3 grid above.
There are two ways to reach the bottom-right corner:

  1. Right -> Right -> Down -> Down
  2. Down -> Down -> Right -> Right Example 2: Input: obstacleGrid = [[0,1],[0,0]] Output: 1 Constraints: m == obstacleGrid.length n ==
    obstacleGrid[i].length 1 <= m, n <= 100 obstacleGrid[i][j] is 0 or 1.

在Unique Paths的基础上增加了障碍,地图上有些块标记为不能通过。输入为二维数组,表示地图上每一点是否可以通过,0表示可以通过,1表示障碍不能通过。
直接通过列举的方法,找到所有的路径,提交结果发现计算超时。
查看了网站的解决方法以后,写下的代码如下:

public class Solution {
    
    public int UniquePathsWithObstacles(int[][] obstacleGrid) {
        int m = obstacleGrid.Length;
            int n = obstacleGrid[0].Length;
            int[,] array_temp = new int[m,n]; 
            if ((m == 0 && n == 0) || obstacleGrid[0][0] == 1) return 0;
            array_temp[0, 0] = 1;
           for (int j = 0; j < n; j++)
            {
                if (obstacleGrid[0][j] == 1) break;
                array_temp[0, j] = 1;
            }
            for (int i = 0; i < m; i++)
            {
                if (obstacleGrid[i][0] == 1) break;
                array_temp[i, 0] = 1;
            }
            for (int i = 1; i < m; i++)
            {
                for (int j = 1; j < n; j++)
                {
                    if (obstacleGrid[i][j] == 1)
                    {
                        array_temp[i, j] = 0;
                    }
                    else 
                    {
                        array_temp[i, j] = array_temp[i-1, j]+ array_temp[i, j-1];
                    }
                }
            }
            return array_temp[m-1,n-1];
    }
}

具体的思路网站上解释的很清楚,我就简单描述下。

  1. 创建路径条数数组[m,n],表示能到该点的路径条数。
  2. 从起点[0,0]开始,起点如果没有障碍,则标记为1。如果起点有障碍,直接结束,返回0。
  3. 接着初始化第一行和第一列,没有遇到障碍就标记为1,一旦遇到障碍就将该位置和剩下的位置标记为0。
  4. 遍历剩下的位置,如果有障碍,直接赋值0,如果没有障碍,取值为上面和左面位置取值和 [m,n] = [m-1,n] + [m,n-1]。
  5. 最后返回 [m-1,n-1]位置的值即可。
    参考网站的简单示意图:
    在这里插入图片描述
    第二周
    78. Subsets
    Given an integer array nums of unique elements, return all possible subsets (the power set).
    The solution set must not contain duplicate subsets. Return the solution in any order.
    Example 1:
    Input: nums = [1,2,3]
    Output: [[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
    Example 2:
    Input: nums = [0]
    Output: [[],[0]]
    Constraints:
    1 <= nums.length <= 10
    -10 <= nums[i] <= 10
    All the numbers of nums are unique.

输入为整型数组,数组中的元素不重复,返回以数组中元素为集合的不重复的子集。具体可以参考题目中的例子。

这又是和组合相关的题目。先解决一个组合的问题:
给一个整型数组[1,2,3,4,5,6],输出元素数量为3的所有子集合。其实就是从5个元素中取出3个元素,所有不重复情况的组合。

 public class Solution
 {
 public static List<IList<int>> GetCombination(int[] source, int n)
        {
            List<IList<int>> result = new List<IList<int>>();
            if (source.Length < n)
            {
                return null;
            }
            else if (source.Length == n) 
            {
                result.Add(source.ToList());
                return result;
            }

            int[] index = new int[n];
            List<IList<int>> list = new List<IList<int>>();
            GetCombination(ref list, source, 0,source.Length-n, index, 1);
            return list;
        }

        private static void GetCombination(ref List<IList<int>> list, int[] source,int from,int to, int[] index,int level) 
        {
            for (int i = from; i <= to; i++)
            {
                //如果数组中有重复的元素需要加这行代码
                //加入这行代码的前提是source是有序数组
                //if (i > from && source[i] == source[i - 1]) continue;
                index[level - 1] = i;
                if (level == index.Length)
                {
                    List<int> temp = new List<int>();
                    for (int j = 0; j < index.Length; j++)
                    {
                        temp.Add(source[index[j]]);
                    }
                    list.Add(temp);
                }
                else 
                {
                    GetCombination(ref list, source, i + 1, to + 1, index, level + 1);
                }
            }
        }
 }
Solution.GetCombination(new int[5] { 1, 2, 3, 4, 5 }, 3);

基本思路如下图:
在这里插入图片描述
解这题的代码:

public class Solution {
    public static List<IList<int>> GetCombination(int[] source, int n)
        {
            List<IList<int>> result = new List<IList<int>>();
            if (source.Length < n)
            {
                return null;
            }
            else if (source.Length == n) 
            {
                result.Add(source.ToList());
                return result;
            }

            int[] index = new int[n];
            List<IList<int>> list = new List<IList<int>>();
            GetCombination(ref list, source, 0,source.Length-n, index, 1);
            return list;
        }

        private static void GetCombination(ref List<IList<int>> list, int[] source,int from,int to, int[] index,int level) 
        {
            for (int i = from; i <= to; i++)
            {
                index[level - 1] = i;
                if (level == index.Length)
                {
                    List<int> temp = new List<int>();
                    for (int j = 0; j < index.Length; j++)
                    {
                        temp.Add(source[index[j]]);
                    }
                    list.Add(temp);
                }
                else 
                {
                    GetCombination(ref list, source, i + 1, to + 1, index, level + 1);
                }
            }
        }
    public IList<IList<int>> Subsets(int[] nums) {
        List<IList<int>> result = new List<IList<int>>();
            result.Add(new List<int>());
            if (nums.Length == 0) return result;
            for (int i = 1; i <= nums.Length; i++)
            {
                result = result.Concat(GetCombination(nums, i)).ToList<IList<int>>();
            }
            return result;
    }
}

90. Subsets II
Given an integer array nums that may contain duplicates, return all possible subsets (the power set).
The solution set must not contain duplicate subsets. Return the solution in any order.
Example 1:
Input: nums = [1,2,2]
Output: [[],[1],[1,2],[1,2,2],[2],[2,2]]
Example 2:
Input: nums = [0]
Output: [[],[0]]
这一题是Subsets的升级版,输入的数组中有重复的元素,和上一题相比。先进行排序,然后再通过组合的函数计算结果。

public class Solution {
    public IList<IList<int>> SubsetsWithDup(int[] nums) {
        List<IList<int>> result = new List<IList<int>>();
            result.Add(new List<int>());
            if (nums.Length == 0) return result;
            //先排序,然后再计算
            for (int i = 0; i < nums.Length-1; i++)
            {
                for (int j = i+1; j < nums.Length; j++)
                {
                    if (nums[i] > nums[j]) 
                    {
                        int temp = nums[i];
                        nums[i] = nums[j];
                        nums[j] = temp;
                    }
                }
            }

            for (int i = 1; i <= nums.Length; i++)
            {
                result = result.Concat(GetCombination(nums, i)).ToList<IList<int>>();
            }
            return result;
    }
    public static List<IList<int>> GetCombination(int[] source, int n)
        {
            List<IList<int>> result = new List<IList<int>>();
            if (source.Length < n)
            {
                return null;
            }
            else if (source.Length == n) 
            {
                result.Add(source.ToList());
                return result;
            }

            int[] index = new int[n];
            List<IList<int>> list = new List<IList<int>>();
            GetCombination(ref list, source, 0,source.Length-n, index, 1);
            return list;
        }

        private static void GetCombination(ref List<IList<int>> list, int[] source,int from,int to, int[] index,int level) 
        {
            for (int i = from; i <= to; i++)
            {
                if (i > from && source[i] == source[i - 1]) continue;
                index[level - 1] = i;
                if (level == index.Length)
                {
                    List<int> temp = new List<int>();
                    for (int j = 0; j < index.Length; j++)
                    {
                        temp.Add(source[index[j]]);
                    }
                    list.Add(temp);
                }
                else 
                {
                    GetCombination(ref list, source, i + 1, to + 1, index, level + 1);
                }
            }
        }
}

因为集合中有重复的元素,函数 private static void GetCombination(ref List<IList> list, int[] source,int from,int to, int[] index,int level) 中和上一题代码不一样的地方是:if (i > from && source[i] == source[i - 1]) continue;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值