引言
有些關於數組的題目說難不難,說簡單的話也非常不簡單,如果稍微在數組操作中加一些限制條件,比如時間複雜度只能是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;
}
所以,當對簡單數組操作的時候,有時候並不簡單,稍微加一個限制條件就有可能難道一個新高度。所以參考那些大神的思路總會讓我有一些感慨。世界之大,山外有山,天外有天呀。總會有新奇的方法來解決,只有不斷的更新不斷的發現,在慢慢迭代的過程中找到一個更好的解決問題的模型,這個不僅需要想法,感覺積累和經驗也是非常重要的,好了,不嘚吧這麼多了,經驗總結到這裏,希望看到的盆友們能夠有所收穫。
斯是陋室惟“汝”德馨!歡迎關注和交流。