力扣hot100—双指针 4题

移动0

感觉算是简单题,但是一时没想出来。
思路其实就是两步:第一步把非0的数字全挤到左边,同时要记录序列的末尾(用第二个指针),第二步把序列末尾到数组结尾的这一区间全部填。

class Solution {
    public void moveZeroes(int[] nums) {
        if(nums.length <= 1) return;
        int cur = 0;
        for(int i = 0; i < nums.length; i++){
            if(nums[i] != 0){ // 不等于0就填左边
                nums[cur] = nums[i];
                cur++;
            }
        }
        for(; cur < nums.length; cur++){
            nums[cur] = 0;
        }
        return;
    }
}

盛水最多的容器

感觉有一点点思路,但是不清晰。看题解:
在初始时,左右指针分别指向数组的左右两端,每次迭代移动一个高度较小的指针。
感觉思路挺简单的,一开始想不出来不应该。

class Solution {
    public int maxArea(int[] height) {
        int res = 0;
        int left = 0;
        int right = height.length - 1;
        while(left < right){
            int h = Math.min(height[left], height[right]);
            res = Math.max(res, h * (right - left));
            // 三目运算符 需要赋值
            int dummy = height[left] > height[right] ? right-- : left++;
        }
        return res;
    }
}

三数之和

第一个版本,错误,只过了几个用例就超出时间限制,二分写的不对。

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        Set<List<Integer>> s = new HashSet<>();
        for(int i = 0; i < nums.length; i++){
            for(int j = nums.length - 1; j > i; j--){
                int k = (i + j) / 2;
                while(k != i && k != j){
                    int sum = nums[k] + nums[i] + nums[j];
                    if(sum == 0){
                        s.add(Arrays.asList(nums[i], nums[j], nums[k]));
                        break;
                    }
                    else if(sum > 0){ // 说明k偏大了
                        k--;
                    }else{
                        k++;
                    }
                }
            }
        }
        return new ArrayList<>(s);
    }
}

GPT4o的二分法,过了100%用例

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        Set<List<Integer>> s = new HashSet<>();
        for (int i = 0; i < nums.length - 2; i++) {
            // 跳过重复的元素
            if (i > 0 && nums[i] == nums[i - 1]) {
                continue;
            }
            // 在剩余数组中进行二分查找
            for (int j = i + 1; j < nums.length - 1; j++) {
                int target = -(nums[i] + nums[j]);
                // 使用二分查找来查找合适的k
                int left = j + 1, right = nums.length - 1;
                while (left <= right) {
                    int mid = left + (right - left) / 2;
                    if (nums[mid] == target) {
                        s.add(Arrays.asList(nums[i], nums[j], nums[mid]));
                        break;
                    } else if (nums[mid] < target) {
                        left = mid + 1;
                    } else {
                        right = mid - 1;
                    }
                }
            }
        }
        return new ArrayList<>(s);
    }
}

真正的官方做法应该是排序+双指针。
因为题解容忍的时间复杂度能够达到On²,首先将数组排序,便于处理。
之后,可以从左往右移动i,并且在“i到nums.length“区间内,寻找另外两个数,记为l与r,l与r相向移动,过程中仍然需要注意去重。这个的解法时间复杂度更低。

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        int len = nums.length;
        if(nums == null || len < 3) return res;
        // 排序
        Arrays.sort(nums);
        for(int i = 0; i < len; i++){
            // 数组排序了 如果i也大于0 就没必要考虑后面的了
            if(nums[i] > 0) break;
            
            //去重
            if(i > 0 && nums[i] == nums[i - 1]) continue;
            int l = i + 1;
            int r = len - 1;
            // 比较的就是 i, l, r三数 i需要固定 l和r可以变动
            while(l < r){
                int sum = nums[i] + nums[l] + nums[r];
                if(sum == 0){
                    res.add(Arrays.asList(nums[i], nums[l], nums[r]));
                    // 继续去重
                    while(l < r && nums[l] == nums[l + 1]) l++;
                    while(l < r && nums[r] == nums[r - 1]) r--;
                    l++;
                    r--;
                }else if(sum < 0){
                    l++;
                }else if(sum > 0){
                    r--;
                }
            }
        }
        return res;
    }
}

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇