栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

Day10/11 递归 / 回溯

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Day10/11 递归 / 回溯

1 21. 合并两个有序链表 1.1 题目

1.2 题解
class Solution {
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {

        if(list1 == null)
            return list2;
        if(list2 == null)
            return list1;

        ListNode mergeList = new ListNode();
        ListNode res = mergeList;
        ListNode p = list1;
        ListNode q = list2;

        while(p != null && q != null){
            if(p.val < q.val){
                mergeList.next = p;
                mergeList = mergeList.next;
                p = p.next;
            }else{
                mergeList.next = q;
                mergeList = mergeList.next;
                q = q.next;
            }
        }

        if(p == null && q == null)
            return res;

        while(p != null){
            mergeList.next = p;
            mergeList = mergeList.next;
            p = p.next;
        }

        while(q != null){
            mergeList.next = q;
            mergeList = mergeList.next;
            q = q.next;
        }

        return res.next;
    }
}

注:自己采用的归并的思想,但是这道题本身还是以递归的思路去做较为合适,这篇文章的题解很好。

2 206. 反转链表 2.1 题目

2.2 题解
class Solution {
    public ListNode reverseList(ListNode head) {
        if(head == null)
            return head;
        
        ListNode p = new ListNode(head.val, null);
        while(head.next != null){
            ListNode q = new ListNode(head.next.val, null);
            q.next = p;
            p = q;
            head = head.next;
        }

        return p;
    }
}

注:第一想法就是头插法,也实现了;看了下题解,递归好重要。

3 77. 组合 3.1 题目

3.2 题解
class Solution {
    public List> combine(int n, int k) {
        List> res = new ArrayList<>();

        if(k <= 0 || k > n)
            return res;

        // 从1开始搜索
        Deque path = new ArrayDeque<>();
        dfs(n, k, 1, path, res);
        return res;
    }

    private void dfs(int n, int k, int begin, Deque path, List> res){
        // 确定递归的终止条件:栈内长度达到组合长度时
        if(path.size() == k){
            res.add(new ArrayList<>(path));
            return;
        }

        // 遍历所有的搜索起点
        for(int i = begin; i <= n - (k - path.size()) + 1; i++){
            // 向路径变量中添加一个数
            path.addLast(i);
            // 下一轮搜索,设置的搜索起点要加 1,因为组合数理不允许出现重复的元素
            dfs(n, k, i + 1, path, res);
            // 重点理解这里:深度优先遍历有回头的过程,因此递归之前做了什么,递归之后需要做相同操作的逆向操作
            path.removeLast();
        }
    }
}

注:这个大佬的回溯题解好好学。

4 46. 全排列 4.1 题目

4.2 题解
class Solution {
    public List> permute(int[] nums) {
        int len = nums.length;
        List> res = new ArrayList<>();
        if(len == 0)
            return res;

        // 记录每一次排列中元素进path的信息
        boolean[] used = new boolean[len];
        List path = new ArrayList<>();
        dfs(nums, len, 0, path, used, res);
        return res;
    }

    private void dfs(int[] nums, int len, int depth, List path, boolean[] used, List> res){
        // 递归终止条件:depth==len,也就是说所有的数已经取完
        if(depth == len){
            res.add(new ArrayList<>(path));
            return;
        }

        // 在还未选择的数中依次选择一个元素作为下一个位置的元素
        for(int i = 0; i < len; i++){
            // 如果该元素并未进path
            if(!used[i]){
                path.add(nums[i]);
                used[i] = true;

                // 继续向下搜索直至path满为止
                dfs(nums, len, depth + 1, path, used, res);
                used[i] = false;
                path.remove(path.size() - 1);
            }
        }

    }
}

注:题解好好看。

5 784. 字母大小写全排列 5.1 题目

5.2 题解
class Solution {
    public List letterCasePermutation(String s) {
        List res = new ArrayList<>();
        char[] path = new char[s.length()];
        dfs(0, s.toCharArray(), res);
        return res;
    }

    private void dfs(int index, char[] s, List res){
        if(index == s.length){
            res.add(new String(s));
            return;
        }

        if(Character.isLetter(s[index])) { //用Character.isLetter()判断是否为字母,很方便
            s[index] = Character.toLowerCase(s[index]);
            dfs(index + 1, s, res); //对于字母保证生成小写的和大写的两种情况
            s[index] = Character.toUpperCase(s[index]);
        } //分别用Character.toLowerCase()和Character.toUpperCase()转化大小写字母,再也不用写判断手动转化啦

        dfs(index + 1, s, res); //不管是数字还是字母都要进入下一个字符
    }
}

注:这道题的细节没搞清楚,题解在此。

6 总结

感觉不管是递归还是回溯问题,都有一定的模板,等刷完所有的题型回来复习这些题,猛刷同类型。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/960822.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号