zoukankan      html  css  js  c++  java
  • LeetCode #448 Find All Numbers Disappeared in an Array 数组

    Description


    
    Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.
    
    Find all the elements of [1, n] inclusive that do not appear in this array.
    
    Could you do it without extra space and in O(n) runtime? You may assume the returned list does not count as extra space.
    
    



    思路


    老年人回炉重造第6天。

    这道题和 #442 是同类型的题,比较tricky,要求时间复杂度O(n),no extra space(题目补充说明了待返回的数组不算在 extra space 里,所以可以开辟一个数组保存算法的结果)

    本题的难点之一是如何正确理解题目,关键信息有两个,一个是所有数字在输入串中只能出现一次,另一个是1 ≤ a[i] ≤ n (n = size of array)。该信息的意思是:数组内所有元素的值都在 1size 之间。

    本来必须有两层循环才能解题,或者将第二层改成 HashSet O(1)~O(n) 的插入与查找。但是根据这两个关键信息,我们可以让内层循环变成常数时间的“映射”,从而使时间复杂度降为 O(n)。内层“映射 Key-Value”的方法是:把元素减一的值作为 index(Key),将 nums[index] 改为负号以便标记一个数字已经访问过了(Value)。

    能这么做的基础有几个:

    • 减一之后,数组内元素值的范围在 0size -1 之间,刚好与 index 相等。
    • 设计合理的映射 / Hash 策略,比如这里的基本原址、从元素值的绝对值标记某个数字已被访问的映射。
    • nums 值被改成负号也没有问题,依旧能用 abs() 表示其原来的值。




    AC之后发现:

    • 对于这种重复数字问题,unoredered_set 查询效率很差,不能保持 O(1),因为相同元素间的碰撞太多了。因此,要根据该数组的特殊性重新定制新的映射 Hash 策略。
    • c++ 两 set 之间做差集操作的效率低,且没有针对 unordered_set 的内置差集操作,而且意外的是,python 代码都比 c++ 代码快上不少。




    第一版AC代码,340ms,ranking 5.5%:

    class Solution {
    public:
        vector<int> findDisappearedNumbers(vector<int>& nums) {
            vector<int> missing_num;
            unordered_set<int> num_set;
            for (int element : nums) {
                num_set.insert(element);
            }
            
            for (int i = 1; i <= nums.size(); ++i) {
                auto num_set_iter = num_set.find(i);
                if (num_set_iter == num_set.end()) {
                    missing_num.push_back(i);
                }
            }
            
            return missing_num;
        }
    };
    




    第二版AC代码,python 712ms, ranking 5.5%;cpp 912ms,ranking 5% ::

    class Solution:
        def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
            a = set([i for i in range(1, len(nums)+1)])
            b = set(nums)
            return list(a - b)
    
    class Solution {
    public:
        vector<int> findDisappearedNumbers(vector<int>& nums) {
            set<int> all_nums;
            for (int i = 1; i <= nums.size(); ++i) {
                all_nums.insert(i);
            }
    
            set<int> nums_set(nums.begin(), nums.end());
    
            set<int> missing_num;
            set_difference(all_nums.begin(), all_nums.end(),
                           nums_set.begin(), nums_set.end(),
                           inserter(missing_num, missing_num.begin()));
    
            return vector<int>(missing_num.begin(), missing_num.end());
        }
    };
    




    第三版AC代码,116ms,ranking 64%:

    class Solution {
    public:
        vector<int> findDisappearedNumbers(vector<int>& nums) {
            if (nums.empty()) return nums;
            
            vector<int> result;
            
            for (auto element : nums) {
                // element may be negative, don't use it directly as index
                element = abs(element);
                
                if (nums[element-1] > 0) {
                    nums[element-1] = -nums[element-1];
                }
            }
            
            for (int i = 0; i < nums.size(); ++i) {
                if (nums[i] > 0) {
                    result.push_back(i+1);
                }
            }
                
            return result;
        }
    };
    



  • 相关阅读:
    PHP 获取当前url的函数及参数
    PHP 和 AJAX responseXML 实例
    PHP 和 AJAX 投票
    AJAX技术在PHP开发中的简单应用
    摄影教程
    结合 Ajax 进行 PHP 开发
    CSS 格式验证器
    swfobject.js,这个JS究竟有什么作用呢
    PHP中Date获取时间不正确怎么办
    用来给不愿意用iframe的同志的页面引用的解决办法
  • 原文地址:https://www.cnblogs.com/Bw98blogs/p/12642407.html
Copyright © 2011-2022 走看看