leetcode-645 leetcode-442 总结-------“数组”查找重复数系列

引言

有些关于数组的题目说难不难,说简单的话也非常不简单,如果稍微在数组操作中加一些限制条件,比如时间复杂度只能是O(n),空间复杂度只能是O(1)或者O(n),那么这样的题就跟数学题和智力题一样很考验人。

类似题目

leetcode-645 错误的集合;leetcode-442 数组中重复的元素;

解题思路:

刚开始的时候,我之前都是第一印象是对原来数组进行排序,这样一来数组中的数据假如题目中给的数据是【1-n】的话,那么大概可以各自归位了,即nums[i]=i+1.但是呢,这样的方法是不可取的,一是因为假如重复的数如果在排序之后并不是挨着的,例如LeetCode-645中的一个测试用例【3,2,3,4,6,5】,重复的3和缺少的1就没有挨着。所以经过查看网上大神们的做题思路,感觉很新奇:

他们并不是对原来的数据进行修改,而是对其符号进行修改,遇到nums[i]那么就把下标为nums[i]-1的这个元素符号进行反转:

  • 如果为正,那么就把下标为nums[i]-1的元素符号更换
  • 如果为负,说明之前下标为nums[i]-1的元素已经存在了,那么就可以立马找到重复的那个数就是nums[i].就可以直接把重复的结果找到。

例如leetcode-645 错误的集合:参考https://blog.csdn.net/woshichaoren000/article/details/76147116的杰作:

vector<int> findErrorNums(vector<int>& nums) {
        vector <int> ans;
        for (int i = 0; i < nums.size(); i++) {
            int index = abs(nums[i]) - 1;
            if (nums[index] > 0) {
                nums[index] *= -1;
            }
            else {
                ans.push_back(index + 1);
            }
        }
        for (int i = 0; i < nums.size(); i++) {
            if (nums[i] > 0) {
                ans.push_back(i + 1);
            }
        }
        return ans;
    }

就是我刚才说的思路。

leetcode-442使用相同的思路完全可以解决,而且时间复杂度只有O(N),空间复杂度只有O(1)。参考大神https://blog.csdn.net/bengepai/article/details/79200450的代码入下:

vector<int> findDuplicates(vector<int>& nums) {
        vector<int> result;
        for(int i=0;i<nums.size();i++)
        {
            nums[abs(nums[i])-1]=-nums[abs(nums[i])-1];//将当前值所对应的索引的值变为相反数。
            if(nums[abs(nums[i])-1]>0)//大于0,说明该数变过2次,说明对应的索引出现了2次,索引即为重复数字(因为没有5,6所以他根本不会查看5,6的下标是否为正负,所以就可以解决,6,5对应下标也是正数的情况)
                result.push_back(abs(nums[i]));
        }

        return result;
    }

所以,当对简单数组操作的时候,有时候并不简单,稍微加一个限制条件就有可能难道一个新高度。所以参考那些大神的思路总会让我有一些感慨。世界之大,山外有山,天外有天呀。总会有新奇的方法来解决,只有不断的更新不断的发现,在慢慢迭代的过程中找到一个更好的解决问题的模型,这个不仅需要想法,感觉积累和经验也是非常重要的,好了,不嘚吧这么多了,经验总结到这里,希望看到的盆友们能够有所收获。

斯是陋室惟“汝”德馨!欢迎关注和交流。

发布了28 篇原创文章 · 获赞 15 · 访问量 8276

猜你喜欢

转载自blog.csdn.net/weixin_38976558/article/details/88344945