力扣爆刷第168天之TOP200五连刷106-110(每日温度单调栈、盛水最多滑动窗口、全排列回溯)

力扣爆刷第168天之TOP200五连刷106-110(每日温度单调栈、盛水最多滑动窗口、全排列回溯)

一、138. 随机链表的复制

题目链接:https://leetcode.cn/problems/copy-list-with-random-pointer/description/
思路:本题求的是随机链表的复制,其实就是把链表复制一份出来,但是要求深拷贝,其实也很简单,需要先把链表next的这一条链给复制一遍,并且在复制的过程中用map进行记录,原链表节点为key,拷贝链表节点为value,这样在复制完next链以后,再遍历一遍原链表的每一个节点的random,就可以利用map找到在拷贝链表中对应的节点。
在这里插入图片描述

class Solution {
    public Node copyRandomList(Node head) {
        Map<Node, Node> map = new HashMap<>();
        Node root = new Node(-1);
        Node p1 = head, p2 = root;
        while(p1 != null) {
            p2.next = new Node(p1.val);
            p2 = p2.next;
            map.put(p1, p2);
            p1 = p1.next;
        }
        p1 = head;
        p2 = root.next;
        while(p1 != null) {
            p2.random = map.get(p1.random);
            p1 = p1.next;
            p2 = p2.next;
        }
        return root.next;
    }
}

二、739. 每日温度

题目链接:https://leetcode.cn/problems/daily-temperatures/description/
思路:求对于每一天来说,下一个大于今天温度的天,在几天之后,让求这个。一看就是使用单调栈,本质上维护一个从栈底到栈顶单调递减的栈,如果当前元素的值大于栈顶了,那么栈顶出栈,对于栈顶元素来说,外面的这个元素就是第一个大于他的,然后还要继续出栈,直到栈内没有小于外部元素的元素即可。

class Solution {
    public int[] dailyTemperatures(int[] temperatures) {
        int len = temperatures.length;
        int[] res = new int[len];

        LinkedList<Integer> stack = new LinkedList<>();
        for(int i = 0; i < len; i++) {
            while(!stack.isEmpty() && temperatures[i] > temperatures[stack.peek()]) {
                int t = stack.pop();
                res[t] = i - t;
            }
            stack.push(i);
        }
        return res;
    }
}

三、136. 只出现一次的数字

题目链接:https://leetcode.cn/problems/single-number/description/
思路:本题是一个利用运算符的题,只有一个元素出现一次,其他都出现两次,那么可以利用异或的特性,相同为0,不同为1。
举个例子:
1 1 0、0 0 1、 1 1 0一共三个数:
1 1 0 ^ 0 0 1 = 1 1 1;
1 1 1 ^ 1 1 0 = 0 0 1.

class Solution {
    public int singleNumber(int[] nums) {
        int res = 0;
        for(int n : nums) {
            res ^= n;
        }
        return res;
    }
}

四、11. 盛最多水的容器

题目链接:https://leetcode.cn/problems/container-with-most-water/
思路:求左右边界与x轴围起来的最大面积,不同与接雨水,本题只需要维护一个最大的滑动窗口,不断记录窗口面积,如果左边界小于右边界,那么可以把左边界向右移动,如果右边界小于左边界,那么可以把右边界向左移动。这样当左右边界相遇,在过程中一定记录下来了最大窗口面积。

class Solution {
    public int maxArea(int[] height) {
        int left = 0, right = height.length-1;
        int max = 0;
        while(left < right) {
            max = Math.max(max, Math.min(height[left], height[right]) * (right - left));
            if(height[left] <= height[right]) left++;
            else right--;
        }
        return max;
    }
}

五、47. 全排列 II

题目链接:https://leetcode.cn/problems/permutations-ii/description/
思路:我先把回溯题的心法写在下面:
回溯类型的题目一共就分两类:组合和排列。
然后又细分为:
①、元素无重,不可复选。
②、元素可重,不可复选。
③、元素无重,可复选。
本题是排列,而且有重复元素,不可复选,那么可以排列一下,又因为是排序,不需要指定起始位置,每次递归遍历都是从0开始,所以需要纵向去重,避免单个元素重复使用。另外又因为数组本身就有重复元素,如果1 1 2,排列之后会出现 第一个1和第二个1,与,第二个1和第一个1.那么需要横向去重,这个是需要排序使用的。

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> list = new ArrayList<>();
    boolean[] flag;
    public List<List<Integer>> permuteUnique(int[] nums) {
        Arrays.sort(nums);
        flag = new boolean[nums.length];
        backTracking(nums);
        return res;
    }
    
    void backTracking(int[] nums) {
        if(list.size() == nums.length) {
            res.add(new ArrayList(list));
            return;
        }
        for(int i = 0; i < nums.length; i++) {
            if(flag[i] || (i > 0 && nums[i] == nums[i-1]) && !flag[i-1]) continue;
            flag[i] = true;
            list.add(nums[i]);
            backTracking(nums);
            flag[i] = false;
            list.remove(list.size()-1);
        }
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

当年拼却醉颜红

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值