Leetcode做题记录-5.30

本文记录了在LeetCode上解决的几道经典算法题,包括一维数组动态和、不同整数的最少数目、正则表达式匹配、装水最多的容器以及错误的集合问题。解题思路涉及双重循环、Map排序、动态规划和状态转移等方法,对提升算法能力有一定帮助。

1.一维数组动态和:自己做出来了

给你一个数组 nums 。数组「动态和」的计算公式为:runningSum[i] = sum(nums[0]…nums[i]) 。

请返回 nums 的动态和。

解题思路:我是用的双重for循环来做,赋值到一个新的数组,官方给的方法是用++对原数组进行循环

//我的思路:
class Solution {
    public int[] runningSum(int[] nums) {
        int[] sum = new int[nums.length];
        for(int i=0;i<nums.length;i++)
        {
            if(i==0)
            {
                sum[i]=nums[i];
            }
            else
            {
                for(int j=0;j<=i;j++)
                {
                    sum[i]=sum[i]+nums[j];
                }
            }
        }
        return sum;
    }
}

//官方思路:
class Solution {
    public int[] runningSum(int[] nums) {
        int n = nums.length;
        for (int i = 1; i < n; i++) {
            nums[i] += nums[i - 1];//这句循环++的操作是核心
        }
        return nums;
    }
}

/* 作者:LeetCode-Solution
链接:https://leetcode.cn/problems/running-sum-of-1d-array/solution/yi-wei-shu-zu-de-dong-tai-he-by-leetcode-flkm/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。*/

2.不同整数的最少数目:

给你一个整数数组 arr 和一个整数 k 。现需要从数组中恰好移除 k 个元素,请找出移除后数组中不同整数的最少数目。

解题思路:先把每个整数出现的次数和整数放入一个map表中,然后重要的是对map表进行排序,这样才在删除时先删除出现次数少的,留下不同整数的最少数目,考察Map,List排序

//官方思路:
class Solution {
        public int findLeastNumOfUniqueInts(int[] arr, int k) {
        Map<Integer, Integer> group = new HashMap<>();
        for (int num : arr) {
            int count = group.getOrDefault(num, 0) + 1;
            group.put(num, count);
        }

        List<int[]> freq = new ArrayList<>();
        /**
         * 这个
         */
        for (Map.Entry<Integer, Integer> entry : group.entrySet()) {
            int[] keyValue = {entry.getKey(), entry.getValue()};
            freq.add(keyValue);
        }
        freq.sort(Comparator.comparingInt(keyValue -> keyValue[1]));
        //下面这段代码的排序我看不懂,用idea改成上面的就容易看明白了,可能下面的return还是返回按照[1]排序,可能是这样.
        /*Collections.sort(freq, new Comparator<int[]>() {
            public int compare(int[] keyValue1, int[] keyValue2) {
                return keyValue1[1] - keyValue2[1];
            }
        });*/
        int ans = freq.size();
        for (int[] ints : freq) {
            int occ = ints[1];
            if (k >= occ) {
                --ans;
                k -= occ;
            } else {
                break;
            }
        }
        return ans;
    }
}

3.正则表达式匹配:这道题目还没看懂,要多研究—动态规划+状态转移

给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.’ 和 ‘*’ 的正则表达式匹配。

‘.’ 匹配任意单个字符
‘*’ 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。

解题思路:动态规划,*+前面的字母可以视为空,那么就可以匹配(i=?j-2)来判断t/f利用状态转移表格来做,每个位置有一个初始状态,然后写出每个位置的后续状态,看最后一个状态是T/F.

//官方思路:
class Solution {
    public boolean isMatch(String s, String p) {
        int m = s.length();
        int n = p.length();

        boolean[][] f = new boolean[m + 1][n + 1];//这个布尔数组要大一点,因为0行0列需要空值
        f[0][0] = true;
        for (int i = 0; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                if (p.charAt(j - 1) == '*') {
                    f[i][j] = f[i][j - 2];//每个位置的状态由前一个位置的状态决定
                    if (matches(s, p, i, j - 1)) {
                        f[i][j] = f[i][j] || f[i - 1][j];
                    }
                } else {
                    if (matches(s, p, i, j)) {
                        f[i][j] = f[i - 1][j - 1];
                    }
                }
            }
        }
        return f[m][n];
    }

    public boolean matches(String s, String p, int i, int j) {
        if (i == 0) {
            return false;
        }
        if (p.charAt(j - 1) == '.') {
            return true;
        }
        return s.charAt(i - 1) == p.charAt(j - 1);
    }
}

4.装水最多的容器:

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明:你不能倾斜容器。

解题思路:我写了一个穷举法,结果超时了,妈的,官方的好方法是双指针,从两头开始找,这样找更快速,并且使用了Math.max函数,使运行更快.

//官方思路:
class Solution {
    public int maxArea(int[] height) {
        int l = 0, r = height.length - 1;
        int ans = 0;
        while (l < r) {
            int area = Math.min(height[l], height[r]) * (r - l);
            ans = Math.max(ans, area);
            if (height[l] <= height[r]) {
                ++l;
            }
            else {
                --r;
            }
        }
        return ans;
    }
}

5.错误的集合:默认后面一个相同的是出错的数

集合 s 包含从 1 到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合 丢失了一个数字 并且 有一个数字重复 。

给定一个数组 nums 代表了集合 S 发生错误后的结果。

请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。

解题思路:先对数组进行排序,然后遍历数组,类似1,2,2,4,则先把后面2放入err[0],然后遍历到4,4-2>1,则err[1]=2+1=3,类似1,3,3,4,则先找到3-1>1,err[1]=1+1=2,再找到第二个3,放入err[0]中.

//官方思路:
class Solution {
    public int[] findErrorNums(int[] nums) {
        int[] errorNums = new int[2];
        int n = nums.length;
        Arrays.sort(nums);
        int prev = 0;
        for (int i = 0; i < n; i++) {
            int curr = nums[i];
            if (curr == prev) {
                errorNums[0] = prev;
            } else if (curr - prev > 1) {
                errorNums[1] = prev + 1;
            }
            prev = curr;
        }
        //最后一位出错,就这样处理
        if (nums[n - 1] != n) {
            errorNums[1] = n;
        }
        //Array.sort(errorNums);这个不需要,因为默认err[1]放的是原来的数.
        return errorNums;
    }
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值