zoukankan      html  css  js  c++  java
  • 【LeetCode-数组】有序数组中的单一元素

    题目描述

    给定一个只包含整数的有序数组,每个元素都会出现两次,唯有一个数只会出现一次,找出这个数。
    示例:

    输入: [1,1,2,3,3,4,4,8,8]
    输出: 2
    
    输入: [3,3,7,7,10,11,11]
    输出: 10
    

    注意:
    您的方案应该在 O(log n)时间复杂度和 O(1)空间复杂度中运行。

    题目链接: https://leetcode-cn.com/problems/single-element-in-a-sorted-array/

    思路1

    将数组中的值进行异或,最终的结果就是只出现一次的数字。

    class Solution {
    public:
        int singleNonDuplicate(vector<int>& nums) {
            int ans = nums[0];
            for(int i=1; i<nums.size(); i++){
                ans ^= nums[i];
            }
            return ans;
        }
    };
    

    这种思路没有用到数组有序这个条件,而且时间复杂度为 O(n),不是题目要求的 O(log n)。

    • 时间复杂度:O(n)
    • 空间复杂度:O(1)

    思路2

    题目要求时间复杂度为 O(log n),这就在暗示我们使用二分查找来做。二分查找的关键点就是如何更新 left 和 right。假设当前查找的范围为 [left, right],mid = (left+right)/2。如果 mid 为偶数,则说明 mid 前面有偶数个数,例如 mid = 2,则 mid 前面有 2 个数(下标为 0, 1);如果 mid 为奇数,则说明 mid 前面有奇数个数。

    如果 mid 为偶数,则 mid 前面有偶数个数,我们判断 nums[mid] 和 nums[mid+1] 是否相等。

    • 如果两者相等,则说明前面偶数个数字都是出现两次的数字。例如,数组为 [1,1,2,2,3],mid == 2 为偶数,nums[mid]==nums[mid+1]==2,所以 mid 前面的偶数个数字都出现了两次(两个 1),则出现一次的数字在 mid 右边,此时我们更新 left = mid + 1;
    • 否则,如果 nums[mid] 和 nums[mid+1] 不相等,则出现一次的数字在 mid 左边,此时更新 right = mid - 1。例如,数组为 [1,2,2,3,3],mid == 2,nums[mid]!=nums[mid+1], 1 在 mid 左边。

    如果 mid 为奇数,则 mid 前面有奇数个数,我们同样判断 nums[mid] 和 nums[mid+1] 是否相等。

    • 如果两者相等,则说明只出现一次的数在 mid 左边,更新 right = mid - 1。例如,数组为 [1,2,2,3,3,4,4],mid == 3 为奇数,nums[mid]==nums[mid+1],所以 1 在 mid 左边。
    • 否则,如果两者不等,则说明只出现一次的数在 mid 右边,更新 left = mid + 1。例如,数组为 [1,1,2,2,3,3,4],mid==3,nums[mid]!=nums[mid+1],所以 4 在 mid 右边。

    总结一下:

    • 首先判断 mid 的奇偶性,通过 mid 的奇偶性可以知道 mid 前有奇数个元素还是偶数个元素,然后通过 nums[mid] 和 nums[mid+1] 是否相等来缩小查找范围。
    • 如果 mid 为偶数:
      • 判断 nums[mid] 和 nums[mid+1] 是否相等:
        • 相等,则更新 left = mid + 1;
        • 不等,则更新 right = mid - 1;
    • 如果 mid 为奇数:
      • 判断 nums[mid] 和 nums[mid+1] 是否相等:
        • 相等,则更新 right = mid - 1;
        • 不等,则更新 left = mid + 1;

    代码如下:

    class Solution {
    public:
        int singleNonDuplicate(vector<int>& nums) {
            int left = 0;
            int right = nums.size()-1;
            while(left<=right){
                int mid = left+(right-left)/2;
                if(mid%2==0 && mid+1<nums.size()){ // mid 为偶数
                    if(nums[mid]==nums[mid+1]) left = mid+1;   // nums[mid]==nums[mid+1]
                    else right = mid-1;
                }else if(mid%2!=0 && mid+1<nums.size()){  // mid 为奇数
                    if(nums[mid]==nums[mid+1]) right = mid-1;  // nums[mid]==nums[mid+1]
                    else left = mid+1;
                }else return nums[mid];  // 注意这一步说明 mid 为最后一个元素
            }
            return nums[left];  // 最后返回 nums[left]
        }
    };
    
    • 时间复杂度:O(logn)
    • 空间复杂度:O(1)

    参考

    https://leetcode-cn.com/problems/single-element-in-a-sorted-array/solution/python3-qing-xi-si-lu-yong-shi-ji-bai-97nei-cun-ji/

  • 相关阅读:
    atitit.nfc 身份证 银行卡 芯片卡 解决方案 attilax总结
    atitit.php 流行框架 前三甲为:Laravel、Phalcon、Symfony2 attilax 总结
    Atitit.执行cmd 命令行 php
    Atitit. 图像处理jpg图片的压缩 清理垃圾图片 java版本
    atitit。企业组织与软件工程的策略 战略 趋势 原则 attilax 大总结
    atitit. 管理哲学 大毁灭 如何防止企业的自我毁灭
    Atitit.java的浏览器插件技术 Applet japplet attilax总结
    Atitit.jquery 版本新特性attilax总结
    Atitit. 软件开发中的管理哲学一个伟大的事业必然是过程导向为主 过程导向 vs 结果导向
    (转)获取手机的IMEI号
  • 原文地址:https://www.cnblogs.com/flix/p/13568355.html
Copyright © 2011-2022 走看看