You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LeetCode 540题代码运行异常及末尾语句疑问求助

LeetCode 540. Single Element in a Sorted Array 问题排查与修正

一、代码错误原因及修复

你提供的代码在输入{1,2,3,3,4,4,8,8}时输出8而非2,核心问题出在二分查找的方向判断逻辑错误,以及循环结束后的返回逻辑不严谨:

错误分析

  1. 二分条件逻辑颠倒:
    对于有序数组中成对出现的元素,单个元素左侧的偶数索引i应满足nums[i] == nums[i+1],右侧的偶数索引i应满足nums[i] == nums[i-1]。原代码中对偶数/奇数索引的判断逻辑完全搞反,导致搜索范围错误收缩,最终错过正确元素。
  2. 循环结束后返回逻辑错误:
    循环结束时left和right是相邻索引,此时需要判断两者对应的元素哪个是单个元素,而非直接返回数组首元素或尾元素。

修复后的代码

public class Main {
    public static void main(String[] args) {
        int[] n = {1,2,3,3,4,4,8,8};
        int ans = singleNonDuplicate(n);
        System.out.println(ans); // 输出2
    }

    private static int singleNonDuplicate(int[] nums) {
        int left = 0;
        int right = nums.length - 1;

        while (left < right) {
            int mid = left + (right - left) / 2;
            // 确保mid是偶数,统一判断逻辑
            if (mid % 2 == 1) {
                mid--;
            }
            // 偶数索引mid的元素与mid+1相等,说明单个元素在右侧
            if (nums[mid] == nums[mid + 1]) {
                left = mid + 2;
            } else {
                // 不相等,说明单个元素在左侧或就是mid
                right = mid;
            }
        }
        // 循环结束时left==right,即为单个元素的索引
        return nums[left];
    }
}

若要保留原循环结构,可修正判断逻辑如下:

private static int singleNonDuplicate(int[] nums) {
    int left = 0;
    int right = nums.length - 1;

    while (left + 1 < right) {
        int mid = (left + right) / 2;
        int num = nums[mid];
        // 先判断mid是否为单个元素
        if (num != nums[mid - 1] && num != nums[mid + 1]) {
            return num;
        }

        if (mid % 2 == 0) {
            // 偶数索引,正常应与mid+1相等,相等则单个元素在右侧
            if (num == nums[mid + 1]) {
                left = mid;
            } else {
                // 不相等,单个元素在左侧
                right = mid;
            }
        } else {
            // 奇数索引,正常应与mid-1相等,相等则单个元素在右侧
            if (num == nums[mid - 1]) {
                left = mid;
            } else {
                // 不相等,单个元素在左侧
                right = mid;
            }
        }
    }

    // 循环结束后判断left和right哪个是单个元素
    if (left == 0) {
        return nums[left];
    }
    return nums[left] == nums[left - 1] ? nums[right] : nums[left];
}

二、原代码末尾if (left == 0) return nums[0]语句的作用

原代码中这条语句是试图处理单个元素位于数组第一个位置的情况,比如输入{1,2,2,3,3}:

  • 循环结束时left会停在0,right停在1,此时直接返回nums[0]就能得到正确结果。
    但由于原代码的二分逻辑错误,这条语句无法覆盖所有场景,反而在你的测试用例中导致错误判断。

正确场景下,当单个元素在数组开头时,循环结束后left为0,此时nums[0]必然不等于nums[1],返回它是合理的,但原代码的整体逻辑缺陷让这条语句的作用无法正常发挥。

内容的提问来源于stack exchange,提问作者user19482128

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 22:39:25