Java回溯知识点(含面试大厂题和源码)

慈云数据 2024-03-23 技术支持 77 0

回溯算法是一种通过遍历所有可能的候选解来寻找所有解的算法,如果候选解被确认不是一个解(或至少不是最后一个解),回溯算法会通过在上一步进行一些变化来丢弃这个解,即“回溯”并尝试另一个候选解。回溯法通常用递归方法来实现,在解决排列、组合、选择问题时非常有效。

Java回溯知识点(含面试大厂题和源码)
(图片来源网络,侵删)

回溯算法的核心要点:

  1. 路径:也就是已经做出的选择。
  2. 选择列表:也就是你当前可以做的选择。
  3. 结束条件:也就是到达决策树底层,无法再做出选择的条件。

回溯算法的框架:

回溯算法的基本形式大致如下:

void backtrack(路径, 选择列表) {
    if (满足结束条件) {
        result.add(路径);
        return;
    }
    for (选择 : 选择列表) {
        做选择;
        backtrack(路径, 选择列表);
        撤销选择;
    }
}

回溯算法的关键点

  • 递归前做选择:将当前节点加入路径中,同时将其从选择列表移除。
  • 递归:递归前的选择导向下一层决策树。
  • 递归后撤销选择:将之前做的选择撤销,以回溯至上一步,从而尝试下一个选项。

    回溯算法的应用场景

    • 排列问题:要求输出一个集合的所有排列方式,比如全排列问题。
    • 组合问题:要求输出满足条件的所有组合方式,比如组合总和问题。
    • 选择问题:从集合中选出满足条件的所有子集,比如子集问题、分割问题。

      优化技巧:

      • 剪枝:在遍历过程中,对于明显不会得到正确解的情况直接跳过,减少不必要的计算。
      • 使用合适的数据结构:比如使用数组、链表或是集合等,根据问题场景选用最适合的数据结构,以便于添加、删除操作,优化时间复杂度。

        回溯算法通过尝试分步的方式去解决一个问题,在分步解决问题的过程中,当它通过尝试发现现有的分步答案不能得到有效的正确的解答时,它将取消上一步甚至是上几步的计算,再通过其他的可能的分步解答再次尝试寻找问题的答案。回溯法非常适合用来解决由多个步骤组成的问题,每个步骤有多个选项,通过尝试每个选项并回退到上一个步骤,最终找到解决问题的方法。在软件开发面试中,经常会遇到需要编写源码来解决问题的算法题。这里我将为你提供三道面试中常见的算法题及其Java实现,这些题目不仅考察基本编程能力,还考察对特定算法和数据结构的理解和应用

        Java回溯知识点(含面试大厂题和源码)
        (图片来源网络,侵删)

        1. 全排列

        题目描述:给定一个没有重复数字的序列,返回其所有可能的全排列。

        示例:

        输入: [1,2,3]
        输出:
        [
          [1,2,3],
          [1,3,2],
          [2,1,3],
          [2,3,1],
          [3,1,2],
          [3,2,1]
        ]
        

        Java解法:

        public List permute(int[] nums) {
            List list = new ArrayList();
            backtrack(list, new ArrayList(), nums);
            return list;
        }
        private void backtrack(List list, List tempList, int [] nums){
            if(tempList.size() == nums.length){
                list.add(new ArrayList(tempList));
            } else{
                for(int i = 0; i  
        

        2. 合并K个排序链表

        题目描述:合并 k 个排序链表,返回合并后的排序链表。

        示例:

        输入:
        [
          1->4->5,
          1->3->4,
          2->6
        ]
        输出: 1->1->2->3->4->4->5->6
        

        Java解法:

        public ListNode mergeKLists(ListNode[] lists) {
            if(lists.length == 0) return null;
            PriorityQueue queue = new PriorityQueue(lists.length, Comparator.comparingInt(a -> a.val));
            ListNode dummy = new ListNode(0);
            ListNode tail = dummy;
            for(ListNode node : lists)
                if(node != null)
                    queue.add(node);
            while(!queue.isEmpty()){
                tail.next = queue.poll();
                tail = tail.next;
                if(tail.next != null)
                    queue.add(tail.next);
            }
            return dummy.next;
        }
        

        3. 最长连续序列

        题目描述:给定一个未排序的整数数组,找出最长连续序列的长度。

        示例:

        输入: [100, 4, 200, 1, 3, 2]
        输出: 4
        解释: 最长连续序列是 [1, 2, 3, 4]。长度为 4。
        

        Java解法:

        public int longestConsecutive(int[] nums) {
            Set numSet = new HashSet();
            for (int num : nums) {
                numSet.add(num);
            }
            int longestStreak = 0;
            for (int num : numSet) {
                if (!numSet.contains(num - 1)) {
                    int currentNum = num;
                    int currentStreak = 1;
                    while (numSet.contains(currentNum + 1)) {
                        currentNum += 1;
                        currentStreak += 1;
                    }
                    longestStreak = Math.max(longestStreak, currentStreak);
                }
            }
            return longestStreak;
        }
        

        这三道题目分别覆盖了回溯算法、优先队列和哈希表的使用,是面试中常见的算法题类型。理解这些解法的关键思想和代码实现,对准备软件开发面试大有帮助。

微信扫一扫加客服

微信扫一扫加客服

点击启动AI问答
Draggable Icon