备战秋招day8

算法

93. 复原 IP 地址
思路:我们通过StringBuilder来做拼接、删除操作,给了一段ip,我们按每个间隙去分隔,符合就加入分隔情况,然后跳过分隔点,i+2位置继续去回溯检索。

class Solution {
    List<String> res = new LinkedList<>();
    public List<String> restoreIpAddresses(String s) {
        StringBuilder sb = new StringBuilder(s);
        back(sb,0,0);
        return res;
    }
    public void back(StringBuilder s,int index,int count){
        if(count == 3){
            //分隔了三次后就表示可以判断最后一段IP了
            if(isVaild(s,index,s.length()-1)){
                res.add(s.toString());
            }
            return;
        }
        for(int i = index;i<s.length();i++){
            //判断是否符合规则
            if(isVaild(s,index,i)){
                //符合的话,加入StringBuilder
                s.insert(i+1,'.');
                back(s,i+2,count+1);
                s.deleteCharAt(i+1);
            }else{
                break;
            }
        }
    }
    public boolean isVaild(StringBuilder s,int start,int end){
        if(start > end){
            return false;
        }
        //不能包含前导零
        if(s.charAt(start) == '0' && start!=end){
            return false;
        }
        //检查是否在255里
        int num = 0;
        for(int i = start;i<=end;i++){
            int now = s.charAt(i) - '0';
            num = num*10 + now;
            if(num > 255){
                return false;
            }
        }
        return true;
    }
}

78. 子集

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> list = new ArrayList<>();
    public List<List<Integer>> subsets(int[] nums) {
        Arrays.sort(nums);
        back(nums,0);
        return res;
    }
    public void back(int[] nums,int index){
        //我们每次都需要加入
        res.add(new ArrayList<>(list));

        //回溯返回条件
        if(index>=nums.length){
            return;
        }

        //子集
        for(int i = index;i<nums.length;i++){
            list.add(nums[i]);
            back(nums,i+1);
            list.remove(list.size()-1);
        }
    }
}

90. 子集 II

这里的剪枝其实就是跟day7里面有道题是一样的。

class Solution {
    List<List<Integer>> llist = new ArrayList<>();
    List<Integer> list = new ArrayList<>();
    boolean[] used;
    public List<List<Integer>> subsetsWithDup(int[] nums) {
        Arrays.sort(nums);
        used = new boolean[nums.length];
        back(nums,0);
        return llist;
    }
    public void back(int[]nums,int idx){
        //子集问题,开头直接加入集合即可
        llist.add(new ArrayList(list));
        if(idx >= nums.length) return;
        for(int i = idx;i<nums.length;i++){
            //思考如何剪枝
            if(i>0 && nums[i] == nums[i-1] && !used[i-1]){
                continue;
            }
            list.add(nums[i]);
            used[i] = true;
            back(nums,i+1);
            list.remove(list.size()-1);
            used[i] = false;
        }
    }
}

491. 非递减子序列

class Solution {
    //非递减子序列,本题并没有说是按非递减去排序的,不要一上来就去给排序,其实是乱序找非递减子序列
    //因此会出现同一父节点下元素重复使用的情况,我们要排查的就是这个
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> path = new ArrayList<>();
    public List<List<Integer>> findSubsequences(int[] nums) {
        back(nums,0);
        return res;
    }
    public void back(int[]nums,int idx){
        //终止:序列中至少有两个元素
        if(path.size() >= 2){
            res.add(new ArrayList<>(path));
        }
        //负数转化为正数统计
        int[] hash = new int[201];
        for(int i = idx;i<nums.length;i++){
            //如何剪枝:在path非空的时候,非递减    或   出现过该种情况:如4767
            //会出现:47(第一个7),47(第二个7)的情况
            if(!path.isEmpty() && nums[i]<path.get(path.size()-1) || hash[nums[i]+100] == 1){ 
                continue;
            }
            path.add(nums[i]);
            hash[nums[i]+100] = 1;
            back(nums,i+1);
            path.remove(path.size()-1);
        }
    }
}

46. 全排列

class Solution {
    List<List<Integer>> llist = new ArrayList<>();
    List<Integer> list = new ArrayList<>();
    boolean[] used;
    public List<List<Integer>> permute(int[] nums) {
        used = new boolean[nums.length];
        back(nums);
        return llist;
    }
    public void back(int[] nums){
        //终止条件:要求全排列,list.size()满足nums长度即可
        if(list.size() == nums.length){
            llist.add(new ArrayList<>(list));
            return;
        }
        for(int i = 0;i<nums.length;i++){
            if(used[i]) continue;
            list.add(nums[i]);
            used[i] = true;
            back(nums);
            list.remove(list.size()-1);
            used[i] = false;
        }
    }
}

47. 全排列 II

class Solution {
    List<List<Integer>> llist = new ArrayList<>();
    List<Integer> list = new ArrayList<>();
    boolean[] used;
    public List<List<Integer>> permuteUnique(int[] nums) {
        Arrays.sort(nums);
        used = new boolean[nums.length];
        back(nums);
        return llist;
    }
    public void back(int[] nums){
        //终止条件:全排列,list长度要为nums长度
        if(list.size() == nums.length){
            llist.add(new ArrayList<>(list));
            return;
        }
        for(int i = 0;i<nums.length;i++){
            //如何剪枝?这种剪枝做法前提是得排序
            if(used[i] || i>0 && nums[i] == nums[i-1] && !used[i-1]){
                continue;
            }
            list.add(nums[i]);
            used[i] = true;
            back(nums);
            list.remove(list.size()-1);
            used[i] = false;
        }
    }
}

补充知识点

这两天都只能暂时刷算法(因为租房啊搬家啥的)

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值