(若有侵权会及时删除,请联系告知!)
453. 最小操作次数使数组元素相等
给你一个长度为 n 的整数数组,每次操作将会使 n - 1 个元素增加 1 。返回让数组所有元素相等的最小操作次数。
示例1:
输入:nums = [1,2,3]
输出:3
解释:
只需要3次操作(注意每次操作会增加两个元素的值):
[1,2,3] => [2,3,3] => [3,4,3] => [4,4,4]
示例2:
输入:nums = [1,1,1]
输出:0
class Solution {
public:
int minMoves(vector<int>& nums) {
int minValue = *min_element(nums.begin(),nums.end());
int sum = 0;
for(int i = 0; i < nums.size(); i++)
{
sum += (nums[i] - minValue);
}
return sum;
}
};
665. 非递减数列
给你一个长度为 n n n 的整数数组 n u m s nums nums,请你判断在最多改变 1 个元素的情况下,该数组能否变成一个非递减数列。
我们是这样定义一个非递减数列的: 对于数组中任意的 i i i, ( 0 < = i < = n − 2 ) (0 <= i <= n-2) (0<=i<=n−2),总满足 n u m s [ i ] < = n u m s [ i + 1 ] nums[i] <= nums[i + 1] nums[i]<=nums[i+1]。
示例1:
输入: nums = [4,2,3]
输出: true
解释: 你可以通过把第一个 4 变成 1 来使得它成为一个非递减数列。
示例2:
输入: nums = [4,2,1]
输出: false
解释: 你不能在只改变一个元素的情况下将其变为非递减数列。
class Solution {
public:
bool checkPossibility(vector<int>& nums) {
if (nums.size() <= 1) {
return true;
}
int count = 0;
for(int i = 1; i < nums.size() && count < 2; i++)
{
if(nums[i - 1] <= nums[i])
continue;
count++;
if(i - 2 >= 0 && nums[i - 2] > nums[i])
nums[i] = nums[i - 1];
else
nums[i - 1] = nums[i];
}
return count <= 1;
}
};
283. 移动零
给定一个数组 n u m s nums nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例1:
输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]
示例2:
输入: nums = [0]
输出: [0]
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int i = 0,j = 0;
for(int i = 0; i < nums.size(); i++)
{
if(nums[i] != 0)
nums[j++] = nums[i];
}
while(j < nums.size())
nums[j++] = 0;
}
};
53. 最大子数组和
给你一个整数数组 n u m s nums 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
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int n = nums.size();
int *dp = new int[n];
dp[0] = nums[0];
for(int i = 1; i < nums.size(); i++)
{
dp[i] = max(nums[i],nums[i] + dp[i - 1]);
}
int res = -9999999999;
for(int i = 0; i < nums.size(); i++)
{
res = max(res,dp[i]);
}
return res;
}
};
1749. 任意子数组和的绝对值的最大值
给你一个整数数组 nums 。一个子数组 [ n u m s l , n u m s l + 1 , . . . , n u m s r − 1 , n u m s r ] [nums_l, nums_{l+1}, ..., nums_{r-1}, nums_{r}] [numsl,numsl+1,...,numsr−1,numsr]的和的绝对值为 a b s ( n u m s l + n u m s l + 1 + . . . + n u m s r − 1 + n u m s r ) abs(numsl + numsl+1 + ... + numsr-1 + numsr) abs(numsl+numsl+1+...+numsr−1+numsr)。
请你找出 n u m s nums nums 中和的绝对值最大的任意子数组(可能为空),并返回该最大值 。
a b s ( x ) abs(x) abs(x)定义如下:
如果 x x x 是负整数,那么 a b s ( x ) = − x abs(x)= -x abs(x)=−x。
如果 x x x 是非负整数,那么 a b s ( x ) = x abs(x) = x abs(x)=x。
示例1:
输入:nums = [1,-3,2,3,-4]
输出:5
解释:子数组 [2,3] 和的绝对值最大,为 abs(2+3) = abs(5) = 5 。
示例2:
输入:nums = [2,-5,1,-4,3,-2]
输出:8
解释:子数组 [-5,1,-4] 和的绝对值最大,为 abs(-5+1-4) = abs(-8) = 8 。
class Solution {
public:
int maxAbsoluteSum(vector<int>& nums) {
int n = nums.size();
int *plus_dp = new int[n];
int *minus_dp = new int[n];
//base case
plus_dp[0] = nums[0];
minus_dp[0] = nums[0];
for(int i = 1; i < nums.size(); i++)
{
plus_dp[i] = max(nums[i],nums[i] + plus_dp[i - 1]);
minus_dp[i] = min(nums[i], nums[i] + minus_dp[i - 1]);
}
int res1 = -999999999;
int res2 = 9999999999;
for(int i = 0; i < nums.size(); i++)
{
res1 = max(res1,plus_dp[i]);
res2 = min(res2,minus_dp[i]);
}
res1 = abs(res1);
res2 = abs(res2);
if(res1 >= res2)
return res1;
else
return res2;
}
};
189. 轮转数组
给定一个整数数组 n u m s nums nums ,将数组中的元素向右轮转 k k k 个位置,其中 k 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]
具体介绍环状替换和数组翻转算法
class Solution {
public:
void rotate(vector<int>& nums, int k) {
int n = nums.size();
k = k % n;
int count = gcd(n,k);
for(int start = 0; start < count; start++)
{
int current = start;
int prev = nums[start];
do{
int next = (current + k) % n;
swap(nums[next],prev);
current = next;
}while(start != current);
}
}
};
参考美服的翻转算法,原地址
nums = "----->-->"; k =3
result = "-->----->";
reverse "----->-->" we can get "<--<-----"
reverse "<--" we can get "--><-----"
reverse "<-----" we can get "-->----->"
this visualization help me figure it out :)
class Solution {
public:
void reverse(vector<int>& nums, int start, int end) {
while (start < end) {
swap(nums[start], nums[end]);
start += 1;
end -= 1;
}
}
void rotate(vector<int>& nums, int k) {
k %= nums.size();
reverse(nums, 0, nums.size() - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, nums.size() - 1);
}
};
396.旋转函数
示例1:
输入: nums = [4,3,2,6]
输出: 26
解释:
F(0) = (0 * 4) + (1 * 3) + (2 * 2) + (3 * 6) = 0 + 3 + 4 + 18 = 25
F(1) = (0 * 6) + (1 * 4) + (2 * 3) + (3 * 2) = 0 + 4 + 6 + 6 = 16
F(2) = (0 * 2) + (1 * 6) + (2 * 4) + (3 * 3) = 0 + 6 + 8 + 9 = 23
F(3) = (0 * 3) + (1 * 2) + (2 * 6) + (3 * 4) = 0 + 2 + 12 + 12 = 26
所以 F(0), F(1), F(2), F(3) 中的最大值是 F(3) = 26 。
示例2:
输入: nums = [100]
输出: 0
class Solution {
public:
int maxRotateFunction(vector<int>& nums) {
int n = nums.size();
int sum = 0;
int total = 0;
//int *dp = new int[n];
int dp_0 = 0;
int dp_1 = 0;
for(int i = 0; i < n; i++)
{
total += nums[i];
sum += i * nums[i];
}
dp_0 = sum;
int maxValue = dp_0;
for(int k = 1; k < n; k++)
{
dp_1 = dp_0 + total - n * nums[n - k];
dp_0 = dp_1;
maxValue = max(maxValue,dp_0);
//cout << dp[k] << endl;
}
return maxValue;
}
};
88. 合并两个有序数组
题目要求算法复杂度为 O ( m + n ) O(m + n) O(m+n)
思路一:直接在nums1容器中添加元素,最后进行遍历
思路二:(双指针法)由于nums1与nums2已经被排序,我们可以将两个数组看作队列,每次从两个数组头部取出比较小的数字放到结果中。于是我们分别设置m和n为两个数组的头部指针,实例代码如下:
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int *ans = new int[m + n];
int i = 0, j = 0,k = 0;
while(i < m || j < n)
{
if(i == m)
{
ans[k++] = nums2[j++];
}
else if(j == n)
{
ans[k++] = nums1[i++];
}
else if(nums1[i] <= nums2[j])
{
ans[k++] = nums1[i++];
}
else if(nums1[i] > nums2[j])
{
ans[k++] = nums2[j++];
}
}
for(int i = 0; i < m + n; i++)
{
nums1[i] = ans[i];
}
}
};
思路三:由于 n u m s 1 nums1 nums1 的后半部分为空,可以直接覆盖而不会影响结果。因此可以指针设置为从后向前遍历,每次取两者之中的较大者放进 n u m s 1 nums1 nums1 的最后面。由于填补一个空格之后又多出来一个空格,因此示例代码如下:
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int tail = m + n - 1;
m--;
n--;
while(m >= 0 || n >= 0 )
{
if(m < 0)
{
nums1[tail--] = nums2[n--];
}
else if(n < 0)
{
nums1[tail--] = nums1[m--];
}
else if(nums1[m] >= nums2[n])
{
nums1[tail--] = nums1[m--];
}
else if(nums1[m] < nums2[n])
{
nums1[tail--] = nums2[n--];
}
}
}
};