1.python
給定一個整數數組 nums 和一個目標值 target,請你在該數組中找出和爲目標值的那 兩個 整數,並返回他們的數組下標。git
你能夠假設每種輸入只會對應一個答案。可是,你不能重複利用這個數組中一樣的元素。算法
示例:數組
給定 nums = [2, 7, 11, 15], target = 9app
由於 nums[0] + nums[1] = 2 + 7 = 9
因此返回 [0, 1]函數
使用count,返回的是被查找元素的個數。若是有,返回1;不然,返回0。注意,map中不存在相同元素,因此返回值只能是1或0。性能
使用find,返回的是被查找元素的位置,沒有則返回map.end()。測試
//方法二:hashmap //關聯容器是對容器概念的一個改進,將值與鍵關聯在一塊兒 //能夠下降一重時間複雜度 class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { unordered_map<int,int>m; vector<int>res; for (int i=0;i<nums.size();i++) { m[nums[i]]=i; } for (int j=0;j<nums.size();j++) { int t = target- nums[j]; if (m.count(t) && m[t]!=j){//判斷的前後順序必定不能弄錯了 res.push_back(j); res.push_back(m[t]); break; } } return res; } };
11.優化
給定 n 個非負整數 a1,a2,...,an,每一個數表明座標中的一個點 (i, ai) 。在座標內畫 n 條垂直線,垂直線 i 的兩個端點分別爲 (i, ai) 和 (i, 0)。找出其中的兩條線,使得它們與 x 軸共同構成的容器能夠容納最多的水。spa
說明:你不能傾斜容器,且 n 的值至少爲 2。
圖中垂直線表明輸入數組 [1,8,6,2,5,4,8,3,7]。在此狀況下,容器可以容納水(表示爲藍色部分)的最大值爲 49。
示例:
輸入: [1,8,6,2,5,4,8,3,7]
輸出: 49
//由於要求最大面積,因此遊標從兩邊一塊兒卡
class Solution { public: //這個時間複雜度只有O(n) //使用while循環,必定要找準那個讓循環增長或者減小的那個點,很是重要。 //using namespace std; int maxArea(vector<int>& height) { int max = 0, i = 0, j = height.size() - 1; while (i < j) { max = std::max(max,std::min(height[i],height[j]) * (j - i)); if (height[i] < height[j]) i++; else j--; } return max; } }; //這種方法複雜度太大了,儘管結果經過了,能不暴力寫就不要這樣寫 /* int maxArea(vector<int>& height) { int sum = 0;int sum1,sum2; for (int i=0;i<height.size();i++) { for(int j=i+1;j<height.size();j++) { sum1 = (j-i)*height[i]; sum2 = (j-i)*height[j]; if (height[j]>=height[i]&&sum1>=sum) sum = sum1; else if (height[j]<height[i]) { if (sum2>sum) sum = sum2; } } } return sum; }*/
15.
給定一個包含 n 個整數的數組 nums,判斷 nums 中是否存在三個元素 a,b,c ,使得 a + b + c = 0 ?找出全部知足條件且不重複的三元組。
注意:答案中不能夠包含重複的三元組。
例如, 給定數組 nums = [-1, 0, 1, 2, -1, -4],
知足要求的三元組集合爲:
[
[-1, 0, 1],
[-1, -1, 2]
]
1.將數組排序
2.定義三個指針,i,j,k。遍歷i,那麼這個問題就能夠轉化爲在i以後的數組中尋找nums[j]+nums[k]=-nums[i]這個問題,也就將三數之和問題轉變爲二數之和---(可使用雙指針)
//不能借鑑two sum的HashMap方法,就算用set去除重複也很差處理!
Python版本:
class Solution: def threeSum(self, nums: List[int]) -> List[List[int]]: nums.sort() res =[] i = 0 for i in range(len(nums)): if i == 0 or nums[i]>nums[i-1]: l = i+1 r = len(nums)-1 while l < r: s = nums[i] + nums[l] +nums[r] if s ==0: res.append([nums[i],nums[l],nums[r]]) l +=1 r -=1 while l < r and nums[l] == nums[l-1]: l += 1 while r > l and nums[r] == nums[r+1]: r -= 1 elif s>0: r -=1 else : l +=1 return res
C++版本1:(暴力計算確定是超時的)
用雙指針的方法
class Solution { public: vector<vector<int>> threeSum(vector<int>& nums) { vector<vector<int>> three;
vector<int>num; if (nums.size() >=3) { sort(nums.begin(), nums.end()); int first, last; for (int i = 0; i < nums.size() - 2; i++)//這是一個剪枝的過程,對第一個遊標進行處理 { if (i>0 && nums[i] == nums[i - 1])
//後面這個判斷是必須的,爲何呢?由於一樣的數字只能處理一次!(當不須要兩個數字同時用的時候)刪掉會變成[[-1,-1,2],[-1,0,1],[-1,0,1]] continue; first = i + 1; last = nums.size() - 1; int sum; while (first != last)//用first和last兩邊遊標同時逼近是減小時間複雜度的利器 { sum = nums[i] + nums[first] + nums[last]; if (sum < 0) first++; if (sum > 0) last--; if (sum == 0) { if (nums[first] != nums[first - 1]||first==i+1) { num.push_back(nums[i]); num.push_back(nums[first]); num.push_back(nums[last]); three.push_back(num); num.clear();//這一步很是重要! } first++; } } } } return three; } };
C++版本2:(有部分實例通不過,好比000的狀況,繼續思考)這種方法是模仿的two sum的方法!
//暴力計算的方法確定是超時的! class Solution { public: vector<vector<int>> threeSum(vector<int>& nums) { vector<vector<int>>m; unordered_map<int,int> p; //至少要一重循環的 //vector<int>nums1=sort(nums); sort(nums.begin(),nums.end()); if (nums.size()>=3){ for (int i=0;i<nums.size();i++) { p[nums[i]]=i; } for (int i=0;i<nums.size()-2;i++) { if (i>0 && nums[i] == nums[i - 1]) continue; p[nums[i]]=i; vector<int>res; //這個先後可能有重複的,我怎麼判斷呢? for(int j=i+1;j<nums.size()-1;j++) { p[nums[j]]=j; int t = -nums[i]-nums[j]; //由於有兩個-1,這個判斷時候優先判斷的是前面的一個 //if(p[t]<j) if (p.count(t) && p[t]>i && p[t]>j) { res.push_back(nums[i]);res.push_back(nums[j]);res.push_back(t); //break; m.push_back(res); res.clear(); } //m.push_back(res); } } } return m; } };
26.刪除排序數組中的重複項
給定一個排序數組,你須要在原地刪除重複出現的元素,使得每一個元素只出現一次,返回移除後數組的新長度。
不要使用額外的數組空間,你必須在原地修改輸入數組並在使用 O(1) 額外空間的條件下完成。
示例 1:
給定數組 nums = [1,1,2],
函數應該返回新的長度 2, 而且原數組 nums 的前兩個元素被修改成 1, 2。
你不須要考慮數組中超出新長度後面的元素。
示例 2:
給定 nums = [0,0,1,1,1,2,2,3,3,4],
函數應該返回新的長度 5, 而且原數組 nums 的前五個元素被修改成 0, 1, 2, 3, 4。
你不須要考慮數組中超出新長度後面的元素。
說明:
爲何返回數值是整數,但輸出的答案是數組呢?
請注意,輸入數組是以「引用」方式傳遞的,這意味着在函數裏修改輸入數組對於調用者是可見的。
你能夠想象內部操做以下:
// nums 是以「引用」方式傳遞的。也就是說,不對實參作任何拷貝
int len = removeDuplicates(nums);
// 在函數裏修改輸入數組對於調用者是可見的。
// 根據你的函數返回的長度, 它會打印出數組中該長度範圍內的全部元素。
for (int i = 0; i < len; i++) {
print(nums[i]);
}
C++方法1:(這種方法沒有原地修改數組)
class Solution { public: int removeDuplicates(vector<int>& nums) { vector<int>nums1; int len = nums.size(); //nums1[0] = nums[0]; //if (nums != NULL) if(nums.size()==0){ return 0; } nums1.push_back(nums[0]); for (int i=1;i<len;i++) { if(nums[i]!=nums[i-1]) nums1.push_back(nums[i]); } nums = nums1; return nums.size(); } };
C++方法2:(空間開銷比前面一種小)
//用C++雙指針的方法 class Solution { public: int removeDuplicates(vector<int>& nums) { int i=0,j=0; while(j<nums.size()) { int tmp = nums[j]; nums[i++] = nums[j++];//是相等過以後i和j分別+1 while(j<nums.size() && tmp == nums[j]) j++; } return i; } };
35. 搜索插入位置
給定一個排序數組和一個目標值,在數組中找到目標值,並返回其索引。若是目標值不存在於數組中,返回它將會被按順序插入的位置。
你能夠假設數組中無重複元素。
示例 1:
輸入: [1,3,5,6], 5
輸出: 2
示例 2:
輸入: [1,3,5,6], 2
輸出: 1
示例 3:
輸入: [1,3,5,6], 7
輸出: 4
示例 4:
輸入: [1,3,5,6], 0
輸出: 0
Python版本:(二分法查找)
class Solution(object): def searchInsert(self, nums, target): low = 0 high = len(nums) while low < high: mid = low + (high - low)/2 if nums[mid] > target: high = mid elif nums[mid] < target: low = mid +1 else: return mid return low
C++版本1:(這種題目很是簡單)
class Solution { public: int searchInsert(vector<int>& nums, int target) { ////這個數組原本就排好序了 for(int i=0;i<nums.size();i++) { if(target==nums[i]) return i; else if (target<nums[i]) return i; //else // return nums.size(); else if (target>nums[nums.size()-1]) return nums.size(); } return 0; } };
C++版本2:(能夠用lower_bound函數)
class Solution { public: int searchInsert(vector<int>& nums, int target) { int position = lower_bound(nums.begin(),nums.end(),target)-nums.begin(); return position; } };
C++版本3:常規方法----二分法
class Solution { public: int searchInsert(vector<int>& nums, int target) { int low = 0, high = nums.size();//二分法的high最比如最後一個數值位數大一個 int mid; while(low<high) { mid = low+(high-low)/2; if (nums[mid]>target) high = mid; else if (nums[mid]<target) low = mid + 1; else return mid; } return low; } };
53. 最大子序和
給定一個整數數組 nums ,找到一個具備最大和的連續子數組(子數組最少包含一個元素),返回其最大和。
示例:
輸入: [-2,1,-3,4,-1,2,1,-5,4],
輸出: 6
解釋: 連續子數組 [4,-1,2,1] 的和最大,爲 6。
進階:
若是你已經實現複雜度爲 O(n) 的解法,嘗試使用更爲精妙的分治法求解。
//要考慮所有是負數的狀況
Python解法:
class Solution(object): def maxSubArray(self, nums): """ :type nums: List[int] :rtype: int """ for i in range(1, len(nums)): nums[i]= nums[i] + max(nums[i-1], 0) return max(nums)
C++解法一:(只要遍歷兩次)
class Solution { public: //找到一個具備最大和的連續子數組 int maxSubArray(vector<int>& nums) { int ans=0; int max=0; //這個負數的狀況在這個函數裏應該怎麼處理? //if(max(nums)<0) // return std::max(nums);
//考慮所有是負數的狀況 int max1=INT_MIN;//應該是數組的最小範圍了 for(int i=0;i<nums.size();i++){ max1 = std::max(max1,nums[i]); } if (max1<0) return max1; for(int i=0;i<nums.size();i++) { ans+=nums[i]; if (ans<=0) ans=0; if (ans>max) max = ans; } return max; } };
C++解法二:(動態規劃)
這道題根據題目關鍵詞,「最大」「連續」,能夠判斷是一道動態規劃,附上這道題目的wiki連接https://zh.wikipedia.org/wiki/%E6%9C%80%E5%A4%A7%E5%AD%90%E6%95%B0%E5%88%97%E9%97%AE%E9%A2%98 方法以下:
class Solution { public: int maxSubArray(vector<int>& nums) { if(nums.size() == 0) return NULL; int res = INT_MIN; int f_n = -1; for(int i = 0; i < nums.size(); ++i){ f_n = max(nums[i], f_n + nums[i]); res = max(f_n, res); } return res; } };
66. 加一
給定一個由整數組成的非空數組所表示的非負整數,在該數的基礎上加一。
最高位數字存放在數組的首位, 數組中每一個元素只存儲一個數字。
你能夠假設除了整數 0 以外,這個整數不會以零開頭。
示例 1:
輸入: [1,2,3]
輸出: [1,2,4]
解釋: 輸入數組表示數字 123。
示例 2:
輸入: [4,3,2,1]
輸出: [4,3,2,2]
解釋: 輸入數組表示數字 4321。
Python解法一:
(python 先經過list恢復成一個數 而後加1 再恢復成一個list)
class Solution(object): def plusOne(self, digits): """ :type digits: List[int] :rtype: List[int] """ value = 0 length = len(digits) for i in range(length): value += digits[length-i-1]*pow(10,i) value1 = value+1 res=[] while (value1 != 0): p = value1%10 value1 = value1/10 res.append(p) return list(reversed(res))
Python解法二:
class Solution(object): def plusOne(self, digits): """ :type digits: List[int] :rtype: List[int] """ return map(int, str(int(''.join(map(str,digits))) + 1))
C++ 解法:(活用insert函數)
class Solution { public: vector<int> plusOne(vector<int>& digits) { int carry = 1; for(int i = digits.size() - 1 ; i >= 0; i--){ int tmp = (digits[i] + carry) % 10; carry = (digits[i] + carry)/10; digits[i] = tmp; if(carry == 0)//由於這樣,前面就不要動了,能夠節省運行時間 break; } //這是判斷最前面一個數字的狀況 if(carry != 0) digits.insert(digits.begin(),1); return digits; } };
88.合併兩個有序數組
給定兩個有序整數數組 nums1 和 nums2,將 nums2 合併到 nums1 中,使得 num1 成爲一個有序數組。
說明:
初始化 nums1 和 nums2 的元素數量分別爲 m 和 n。
你能夠假設 nums1 有足夠的空間(空間大小大於或等於 m + n)來保存 nums2 中的元素。
示例:
輸入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3
輸出: [1,2,2,3,5,6]
(很是經典、常規的解法)
class Solution { public: void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) { int i1 = m - 1, i2 = n - 1; while(i1 >= 0 && i2 >= 0) { if(nums1[i1] > nums2[i2]) { nums1[i1 + i2 + 1] = nums1[i1]; i1--; } else { nums1[i1 + i2 + 1] = nums2[i2]; i2--; } } //若是是i1的話,多下來的話,直接用,位置不變 while(i2 >= 0) { nums1[i1 + i2 + 1] = nums2[i2]; i2--; } } };
118. 楊輝三角
給定一個非負整數 numRows,生成楊輝三角的前 numRows 行。
在楊輝三角中,每一個數是它左上方和右上方的數的和。
示例:
輸入: 5
輸出:
[
[1],
[1,1],
[1,2,1],
[1,3,3,1],
[1,4,6,4,1]
]
Python解法:
def generate(self, numRows): """ :type numRows: int :rtype: List[List[int]] """ result = [] for i in range(numRows): now = [1]*(i+1) if i >= 2: for n in range(1,i): now[n] = pre[n-1]+pre[n] result += [now] pre = now return result
C++ 解法:
若是單純只是輸出結果,確實不復雜,兩個循環加上一個遞歸方法就能解決問題,代碼也很優雅。可是提交的時候卻沒有經過,提示執行超時,顯示的測試用例是輸入數爲30。仔細閱讀了代碼以後,作了2輪優化。1,遞歸是很是消耗資源的,仔細觀察楊輝三角爲對稱結構,所以只須要遞歸其中一半的數據就能夠,另一半經過循環直接賦值;2,再仔細觀察發現每一行的第二個和倒數第二個值爲行數的值減一,這個特殊的地方能夠直接返回計算值,而不須要遞歸計算,減小性能消耗。兩次優化以後,終於提交成功
class Solution {//速度很是快,很是常規的思路! public: vector<vector<int>> generate(int numRows) { vector<vector<int>> vec(numRows); //至關於動態內存分配,至關於有numRows這麼多的vector<int>結構 if(!numRows)
return vec; vec[0].push_back(1); if(numRows==1) return vec; vec[1].push_back(1); vec[1].push_back(1); if(numRows==2) return vec; for(int i=2;i!=numRows;++i) { vec[i].push_back(1); for(int j=0;j!=i-1;++j) {
vec[i].push_back(vec[i-1][j]+vec[i-1][j+1]);
} vec[i].push_back(1); } return vec; } };
119. 楊輝三角II
給定一個非負索引 k,其中 k ≤ 33,返回楊輝三角的第 k 行。
在楊輝三角中,每一個數是它左上方和右上方的數的和。
示例:
輸入: 3
輸出: [1,3,3,1]
進階:
你能夠優化你的算法到 O(k) 空間複雜度嗎?
//當執行代碼vector<int> v(2,5)時,在內存裏創建了2個整形元素空間,值是5.
//assgin功能:將區間[first,last)的元素賦值到當前的vector容器中,或者賦n個值爲x的元素到vector容器中,這個容器會清除掉vector容器中之前的內容。
C++ 解法1:(沒有看懂)
class Solution { public: vector<int> getRow(int rowIndex) { vector<int> cur(1,1),pre; while(rowIndex--){ pre.assign(cur.begin(), cur.end()); cur.push_back(1); for(int i=1;i<cur.size()-1;i++) cur[i]=pre[i-1]+pre[i]; } return cur; } };
C++解法2:(用到了遞歸的思想)3=1+1+1 比較難想到
class Solution { public: vector<int> getRow(int rowIndex) { vector<int> rows(rowIndex + 1,1);//創建了這麼多整型空間,值是1 for(int i = 0 ; i <= rowIndex; ++i){ for(int j = i - 1 ; j > 0 ; --j){ rows[j] += rows[j-1]; } } return rows; } };
121.買賣股票的最佳時機
給定一個數組,它的第 i 個元素是一支給定股票第 i 天的價格。
若是你最多隻容許完成一筆交易(即買入和賣出一支股票),設計一個算法來計算你所能獲取的最大利潤。
注意你不能在買入股票前賣出股票。
示例 1:
輸入: [7,1,5,3,6,4]
輸出: 5
解釋: 在第 2 天(股票價格 = 1)的時候買入,在第 5 天(股票價格 = 6)的時候賣出,最大利潤 = 6-1 = 5 。
注意利潤不能是 7-1 = 6, 由於賣出價格須要大於買入價格。
示例 2:
輸入: [7,6,4,3,1]
輸出: 0
解釋: 在這種狀況下, 沒有交易完成, 因此最大利潤爲 0。
動態規劃 前i天的最大收益 = max{前i-1天的最大收益,第i天的價格-前i-1天中的最小价格}
Python解法:
class Solution: def maxProfit(self, prices): """ :type prices: List[int] :rtype: int """ min_p, max_p = 999999, 0 for i in range(len(prices)): min_p = min(min_p, prices[i]) max_p = max(max_p, prices[i] - min_p) return max_p
C++ 解法:
(仍是經典的dp思路)
class Solution { public: int maxProfit(vector <int>& prices) {
//簡單動態規劃方法
//這種不斷用到前面結果的題目,用動態規劃是一種好的方法 if(prices.size() <= 1) return 0; int min = prices[0], max = 0; for(int i = 1; i < prices.size(); i++) { max = std::max(max, prices[i] - min); min = std::min(min, prices[i]); } return max; } };
122. 買賣股票的最佳時機II
給定一個數組,它的第 i 個元素是一支給定股票第 i 天的價格。
設計一個算法來計算你所能獲取的最大利潤。你能夠儘量地完成更多的交易(屢次買賣一支股票)。
注意:你不能同時參與多筆交易(你必須在再次購買前出售掉以前的股票)。
示例 1:
輸入: [7,1,5,3,6,4]
輸出: 7
解釋: 在第 2 天(股票價格 = 1)的時候買入,在第 3 天(股票價格 = 5)的時候賣出, 這筆交易所能得到利潤 = 5-1 = 4 。
隨後,在第 4 天(股票價格 = 3)的時候買入,在第 5 天(股票價格 = 6)的時候賣出, 這筆交易所能得到利潤 = 6-3 = 3 。
示例 2:
輸入: [1,2,3,4,5]
輸出: 4
解釋: 在第 1 天(股票價格 = 1)的時候買入,在第 5 天 (股票價格 = 5)的時候賣出, 這筆交易所能得到利潤 = 5-1 = 4 。
注意你不能在第 1 天和第 2 天接連購買股票,以後再將它們賣出。
由於這樣屬於同時參與了多筆交易,你必須在再次購買前出售掉以前的股票。
示例 3:
輸入: [7,6,4,3,1]
輸出: 0
解釋: 在這種狀況下, 沒有交易完成, 因此最大利潤爲 0。
Python解法:
class Solution(object): def maxProfit(self, prices): profit = 0 for day in range(len(prices)-1): differ = prices[day+1] - prices[day] if differ > 0: profit += differ return profit
C++解法:(這道題目沒有那麼難,也不要想的太複雜了)
class Solution { public: int maxProfit(vector<int>& prices) { int res = 0; for (int i = 1; i < prices.size(); i++) if (prices[i] > prices[i - 1])
res += (prices[i] - prices[i - 1]); return res; } };
167. 兩數之和 II - 輸入有序數組
給定一個已按照升序排列 的有序數組,找到兩個數使得它們相加之和等於目標數。
函數應該返回這兩個下標值 index1 和 index2,其中 index1 必須小於 index2。
說明:
返回的下標值(index1 和 index2)不是從零開始的。
你能夠假設每一個輸入只對應惟一的答案,並且你不能夠重複使用相同的元素。
示例:
輸入: numbers = [2, 7, 11, 15], target = 9
輸出: [1,2]
解釋: 2 與 7 之和等於目標數 9 。所以 index1 = 1, index2 = 2 。
C++解法:(指針對撞,減小開銷)去用left和right比,能夠減小一重循環
/*class Solution { public: //這個解法時間開銷太大了 vector<int> twoSum(vector<int>& numbers, int target) { //int count = 0; vector<int>res(2); for (int i=0;i<numbers.size();i++) { for (int j=i+1;j<numbers.size();j++) { if(numbers[i]+numbers[j] == target) { //res.push_back(i+1); //res.push_back(j+1); res[0]=i+1; res[1]=j+1; break; //return res; } //break; } } return res; } };*/ //多用while循環,不要條件反射只會用for //第二種解法屬於指針對撞的解法,能夠下降時間複雜度,複雜度是O(n) //也能夠用二分法,時間複雜度也是O(n) class Solution { public: vector<int> twoSum(vector<int>& numbers, int target) { vector<int> result; int left = 0, right = numbers.size() - 1; while(left < right){ if(numbers[left] + numbers[right] == target){ result.push_back(left + 1); result.push_back(right + 1); break; } else if(numbers[left] + numbers[right] > target){ right--; } else if(numbers[left] + numbers[right] < target){ left++; } } return result; } };
169. 求衆數
給定一個大小爲 n 的數組,找到其中的衆數。衆數是指在數組中出現次數大於 ⌊ n/2 ⌋ 的元素。
你能夠假設數組是非空的,而且給定的數組老是存在衆數。
示例 1:
輸入: [3,2,3]
輸出: 3
示例 2:
輸入: [2,2,1,1,1,2,2]
輸出: 2
從第一個數開始count=1,遇到相同的就加1,遇到不一樣的就減1,減到0就從新換個數開始計數,總能找到最多的那個
C++解法1:
class Solution { public: int majorityElement(vector<int>& nums) { sort(nums.begin(),nums.end()); int i=0; int n=1; while(i<nums.size()-1) { while(i+1<nums.size() && nums[i+1]==nums[i]) { n++; i++; } if(n > (nums.size()/2)) return nums[i]; n=1; i++; } return nums[i]; } };
C++解法2:(本身寫的,比較容易想)
class Solution { public: int majorityElement(vector<int>& nums) { sort(nums.begin(), nums.end()); int count = 1;//1 1 1 2 2 2 2 int i = 1; while(i<nums.size()) { if(nums[i]==nums[i-1]) { count++; if (count>nums.size()/2) return nums[i]; } else if (nums[i]!=nums[i-1]) { count=1; } i++; } return nums[0]; } };
209. 長度最小的子數組
給定一個含有 n 個正整數的數組和一個正整數 s ,找出該數組中知足其和 ≥ s 的長度最小的連續子數組。若是不存在符合條件的連續子數組,返回 0。
示例:
輸入: s = 7, nums = [2,3,1,2,4,3]
輸出: 2
解釋: 子數組 [4,3] 是該條件下的長度最小的連續子數組。
進階:
若是你已經完成了O(n) 時間複雜度的解法, 請嘗試 O(n log n) 時間複雜度的解法。
//這種解法很是好!! class Solution { public: int minSubArrayLen(int s, vector<int>& nums) { int start=-1, minlength=nums.size()+1, sum=0; for (int i=0;i<nums.size();i++) { sum+=nums[i]; while (sum >= s) { minlength=min(minlength, i-start); start++; sum-=nums[start]; } } return minlength == nums.size()+1 ? 0 : minlength; } }; /* //這種解法也能夠,比較容易理解!! class Solution { public: int minSubArrayLen(int s, vector<int>& nums) { int n = nums.size(); int sum = 0; int min = n + 1; for (int start = 0, end = 0; start < n && end < n;) { while (sum < s && end < n) sum += nums[end++]; while (sum >= s && start < n) { if (min > (end - start)) min = end - start; sum -= nums[start++]; } } if (min == (n + 1)) return 0; return min; } };*/
217. 存在重複元素
給定一個整數數組,判斷是否存在重複元素。
若是任何值在數組中出現至少兩次,函數返回 true。若是數組中每一個元素都不相同,則返回 false。
示例 1:
輸入: [1,2,3,1]
輸出: true
示例 2:
輸入: [1,2,3,4]
輸出: false
示例 3:
輸入: [1,1,1,3,3,4,3,2,4,2]
輸出: true
Python解法:(直接用set)
class Solution: def containsDuplicate(self, nums): """ :type nums: List[int] :rtype: bool """ set1 = set(nums) if len(set1) == len(nums): return False else: return True
C++ 解法一:(用map去作,後面的鍵值存儲出現了多少次)
class Solution { public: bool containsDuplicate(vector<int>& nums) { map<int,int> nums1;//一開始默認的初始值就是0 for(int i = 0;i<nums.size();i++) { nums1[nums[i]]++; if(nums1[nums[i]] == 2) return true; } return false; } };
C++解法二: (用set去作)
class Solution { public: bool containsDuplicate(vector<int>& nums) { set<int> s(nums.begin(),nums.end()); if(s.size() != nums.size()) return true; return false; } };
C++解法三:(最普通直接的解法,可是是最快的)
class Solution { public: bool containsDuplicate(vector<int>& nums) { if(nums.empty()) return false;
//注意判斷空的狀況 sort(nums.begin(),nums.end()); for(int i = 0;i<nums.size()-1;i++) { if(nums[i] == nums[i+1]) return true; } return false; } };
219. 存在重複元素II
給定一個整數數組和一個整數 k,判斷數組中是否存在兩個不一樣的索引 i 和 j,使得 nums [i] = nums [j],而且 i 和 j 的差的絕對值最大爲 k。
示例 1:
輸入: nums = [1,2,3,1], k = 3
輸出: true
示例 2:
輸入: nums = [1,0,1,1], k = 1
輸出: true
示例 3:
輸入: nums = [1,2,3,1,2,3], k = 2
輸出: false
class Solution { public: //正常循環判斷解法顯示堆棧溢出,這是爲何呢? bool containsNearbyDuplicate(vector<int>& nums, int k) { unordered_map<int,int> m; for(int i=0;i<nums.size();i++) { if(m.count(nums[i]) && i-m[nums[i]]<=k) return true; m[nums[i]] = i; } return false; } };
414. 第三大的數
給定一個非空數組,返回此數組中第三大的數。若是不存在,則返回數組中最大的數。要求算法時間複雜度必須是O(n)。
示例 1:
輸入: [3, 2, 1]
輸出: 1
解釋: 第三大的數是 1.
示例 2:
輸入: [1, 2]
輸出: 2
解釋: 第三大的數不存在, 因此返回最大的數 2 .
示例 3:
輸入: [2, 2, 3, 1]
輸出: 1
解釋: 注意,要求返回第三大的數,是指第三大且惟一出現的數。
存在兩個值爲2的數,它們都排第二。
Python解法:
class Solution: def thirdMax(self, nums: List[int]) -> int: nums = list(set(nums)) if len(nums) < 3: return max(nums) nums.sort(reverse=True) return nums[2]
C++解法:(用list和set的特性)---速度最好的方法
class Solution { public: int thirdMax(vector<int>& nums) { int small_fir=nums[0],small_sec=INT_MIN,i=1; long res=INT_MIN-1L; while(i<nums.size()&&nums[i]==small_fir) i++; if(i>=nums.size()) return small_fir; small_sec=nums[i]; if(small_fir<small_sec) swap(small_fir,small_sec); for(;i<nums.size();i++) { if(nums[i]<small_sec) res=max((long)nums[i],res); else if(nums[i]>small_fir) { res=small_sec; small_sec=small_fir; small_fir=nums[i]; } else if(nums[i]<small_fir&&nums[i]>small_sec) { res=small_sec; small_sec=nums[i]; } } return res==INT_MIN-1L?small_fir:(int)res; } };
448. 找到全部數組中消失的數字
給定一個範圍在 1 ≤ a[i] ≤ n ( n = 數組大小 ) 的 整型數組,數組中的元素一些出現了兩次,另外一些只出現一次。
找到全部在 [1, n] 範圍之間沒有出如今數組中的數字。
您能在不使用額外空間且時間複雜度爲O(n)的狀況下完成這個任務嗎? 你能夠假定返回的數組不算在額外空間內。
示例:
輸入:
[4,3,2,7,8,2,3,1]
輸出:
[5,6]
【筆記】將全部正數做爲數組下標,置對應數組值爲負值。那麼,仍爲正數的位置即爲(未出現過)消失的數字。
舉個例子:
原始數組:[4,3,2,7,8,2,3,1]
重置後爲:[-4,-3,-2,-7,8
,2
,-3,-1]
結論:[8,2] 分別對應的index爲[5,6](消失的數字)
class Solution { public: vector<int> findDisappearedNumbers(vector<int>& nums) { for (int i = 0; i < nums.size(); ++i) nums[abs(nums[i])-1] = -abs(nums[abs(nums[i])-1]); vector<int> res; for (int i = 0; i < nums.size(); ++i){ if (nums[i] > 0) res.push_back(i+1); } return res; } };
比較容易想,可是有差錯,且使用了額外的空間
class Solution { public: vector<int> findDisappearedNumbers(vector<int>& nums) { sort(nums.begin(),nums.end()); vector<int>nums1; nums1.push_back(nums[0]); for(int i=1;i<nums.size();i++) { if(nums[i]!=nums[i-1]) nums1.push_back(nums[i]); else continue; } vector<int>nums2; for(int i=0;i<nums1.size();i++) { if(nums1[i+1]==nums1[i]+1) continue; else if (nums1[i+1]!=nums1[i]+1) //nums2.push_back(nums[i]+1); { int num = nums1[i+1]-nums1[i]; for(int j=1;j<num;j++) { nums2.push_back(nums1[i]+j); } } } return nums2; } };