53. 最大子數組和
給你一個整數數組
nums
,請你找出一個具有最大和的連續子數組(子數組最少包含一個元素),返回其最大和。子數組是數組中的一個連續部分。
示例 1:
輸入:nums = [-2,1,-3,4,-1,2,1,-5,4] 輸出:6 解釋:連續子數組 [4,-1,2,1] 的和最大,為 6 。
示例 2:
輸入:nums = [1] 輸出:1
示例 3:
輸入:nums = [5,4,-1,7,8] 輸出:23
提示:
1 <= nums.length <= 10^5
-10^4 <= nums[i] <= 10^4
**進階:**如果你已經實現復雜度為
O(n)
的解法,嘗試使用更為精妙的 分治法 求解。
int maxSubArray(vector<int>& nums) {int n = nums.size();// i結尾最大子數組和vector<int> dp(n);dp[0] = nums[0];int ans = dp[0];for (int i = 1; i < n; ++i) {dp[i] = max(dp[i - 1] + nums[i], nums[i]);ans = max(ans, dp[i]);}return ans;
}
56. 合并區間
以數組
intervals
表示若干個區間的集合,其中單個區間為intervals[i] = [starti, endi]
。請你合并所有重疊的區間,并返回 一個不重疊的區間數組,該數組需恰好覆蓋輸入中的所有區間 。示例 1:
輸入:intervals = [[1,3],[2,6],[8,10],[15,18]] 輸出:[[1,6],[8,10],[15,18]] 解釋:區間 [1,3] 和 [2,6] 重疊, 將它們合并為 [1,6].
示例 2:
輸入:intervals = [[1,4],[4,5]] 輸出:[[1,5]] 解釋:區間 [1,4] 和 [4,5] 可被視為重疊區間。
提示:
1 <= intervals.length <= 10^4
intervals[i].length == 2
0 <= starti <= endi <= 10^4
vector<vector<int>> merge(vector<vector<int>>& intervals) {sort(intervals.begin(), intervals.end());vector<vector<int>> ans;for (int i = 0; i < intervals.size(); ++i) {int left = intervals[i][0], right = intervals[i][1];if (ans.empty() || ans.back()[1] < left) {ans.push_back({left, right});} else {ans.back()[1] = max(ans.back()[1], right);}}return ans;
}
189. 輪轉數組
給定一個整數數組
nums
,將數組中的元素向右輪轉k
個位置,其中k
是非負數。示例 1:
輸入: nums = [1,2,3,4,5,6,7], k = 3 輸出: [5,6,7,1,2,3,4] 解釋: 向右輪轉 1 步: [7,1,2,3,4,5,6] 向右輪轉 2 步: [6,7,1,2,3,4,5] 向右輪轉 3 步: [5,6,7,1,2,3,4]
示例 2:
輸入:nums = [-1,-100,3,99], k = 2 輸出:[3,99,-1,-100] 解釋: 向右輪轉 1 步: [99,-1,-100,3] 向右輪轉 2 步: [3,99,-1,-100]
提示:
1 <= nums.length <= 10^5
-2^31 <= nums[i] <= 2^31 - 1
0 <= k <= 10^5
void rotate(vector<int>& nums, int k) {int n = nums.size();k %= n;reverse(nums, 0, n-1);reverse(nums, 0, k-1);reverse(nums, k, n-1);
}void reverse(vector<int>& nums, int left, int right) {while (left < right) {swap(nums[left++], nums[right--]);}
}
238. 除自身以外數組的乘積
給你一個整數數組
nums
,返回 數組answer
,其中answer[i]
等于nums
中除nums[i]
之外其余各元素的乘積 。題目數據 保證 數組
nums
之中任意元素的全部前綴元素和后綴的乘積都在 32 位 整數范圍內。請 **不要使用除法,**且在
O(n)
時間復雜度內完成此題。示例 1:
輸入: nums = [1,2,3,4] 輸出: [24,12,8,6]
示例 2:
輸入: nums = [-1,1,0,-3,3] 輸出: [0,0,9,0,0]
提示:
2 <= nums.length <= 10^5
-30 <= nums[i] <= 30
- 保證 數組
nums
之中任意元素的全部前綴元素和后綴的乘積都在 32 位 整數范圍內**進階:**你可以在
O(1)
的額外空間復雜度內完成這個題目嗎?( 出于對空間復雜度分析的目的,輸出數組 不被視為 額外空間。)
與這題724. 尋找數組的中心下標類似。分別構建從前往后的乘積數組dp1
,以及從后往前的乘積數組dp2
,再初始化ans
數組即可。
vector<int> productExceptSelf(vector<int>& nums) {int n = nums.size();vector<int> dp1(n + 1);dp1[0] = 1;for (int i = 1; i <= n; ++i)dp1[i] = dp1[i - 1] * nums[i - 1];vector<int> dp2(n + 2);dp2[n + 1] = 1;for (int j = n; j > 0; --j)dp2[j] = dp2[j + 1] * nums[j - 1];vector<int> ans(n);for (int i = 0; i < n; ++i)ans[i] = dp1[i] * dp2[i + 2];return ans;
}
在此基礎上還可以優化空間復雜度,先用ans
作為從前往后的乘積數組dp1
,sum作為從后往前的乘積和,再從后往前更新ans。
vector<int> productExceptSelf(vector<int>& nums) {int n = nums.size();vector<int> ans(n);ans[0] = 1;for (int i = 1; i < n; ++i)ans[i] = ans[i - 1] * nums[i - 1];int sum = 1;for (int i = n - 1; i >= 0; --i) {ans[i] *= sum;sum *= nums[i];}return ans;
}
41. 缺失的第一個正數
給你一個未排序的整數數組
nums
,請你找出其中沒有出現的最小的正整數。請你實現時間復雜度為
O(n)
并且只使用常數級別額外空間的解決方案。示例 1:
輸入:nums = [1,2,0] 輸出:3 解釋:范圍 [1,2] 中的數字都在數組中。
示例 2:
輸入:nums = [3,4,-1,1] 輸出:2 解釋:1 在數組中,但 2 沒有。
示例 3:
輸入:nums = [7,8,9,11,12] 輸出:1 解釋:最小的正數 1 沒有出現。
提示:
1 <= nums.length <= 105
-231 <= nums[i] <= 231 - 1
哈希表,時間復雜度O(n),空間復雜度O(n)
int firstMissingPositive(vector<int>& nums) {unordered_set<int> hash;for (int num : nums) {hash.insert(num);}int ans = 1;while (1) {if (!hash.count(ans)) {return ans;}ans++;}return -1;
}
置換,時間復雜度O(n),空間復雜度O(1)
int firstMissingPositive(vector<int>& nums) {int n = nums.size();for (int i = 0; i < n; ++i) {while (nums[i] > 0 && nums[i] <= n && nums[nums[i]-1] != nums[i]) {swap(nums[nums[i] - 1], nums[i]);}}for (int i = 0; i < n; ++i) {if (nums[i] != i + 1) {return i + 1;}}return n + 1;
}