给定一个偶数长度的数组,其中不同的数字代表着不同种类的糖果,每一个数字代表一个糖果。你需要把这些糖果平均分给一个弟弟和一个妹妹。返回妹妹可以获得的最大糖果的种类数。
示例 1:
输入: candies = [1,1,2,2,3,3]
输出: 3
解析: 一共有三种种类的糖果,每一种都有两个。
最优分配方案:妹妹获得[1,2,3],弟弟也获得[1,2,3]。这样使妹妹获得糖果的种类数最多。
示例 2 :
输入: candies = [1,1,2,3]
输出: 2
解析: 妹妹获得糖果[2,3],弟弟获得糖果[1,1],妹妹有两种不同的糖果,弟弟只有一种。这样使得妹妹可以获得的糖果种类数最多。
注意:
数组的长度为[2, 10,000],并且确定为偶数。
数组中数字的大小在范围[-100,000, 100,000]内。
class Solution {
public:
int distributeCandies(vector<int>& candies) {
//方法一:
set<int> s(candies.begin(),candies.end());
return s.size()>(candies.size()>>1)?candies.size()>>1:s.size();
/*方法二:排序+双指针,双指针可以优化为前后元素大小是否相同比较
sort(candies.begin(),candies.end());
int count=1,size=candies.size();
for(int i=0,j=1;j<size;++j){
if(candies[i]!=candies[j]){
++count;
i=j;
}
}
return count>size>>1?size>>1:count;*/
}
};
机器人在一个无限大小的网格上行走,从点 (0, 0) 处开始出发,面向北方。该机器人可以接收以下三种类型的命令:
-2:向左转 90 度
-1:向右转 90 度
1 <= x <= 9:向前移动 x 个单位长度
在网格上有一些格子被视为障碍物。
第 i 个障碍物位于网格点 (obstacles[i][0], obstacles[i][1])
如果机器人试图走到障碍物上方,那么它将停留在障碍物的前一个网格方块上,但仍然可以继续该路线的其余部分。
返回从原点到机器人的最大欧式距离的平方。
示例 1:
输入: commands = [4,-1,3], obstacles = []
输出: 25
解释: 机器人将会到达 (3, 4)
示例 2:
输入: commands = [4,-1,4,-2,4], obstacles = [[2,4]]
输出: 65
解释: 机器人在左转走到 (1, 8) 之前将被困在 (1, 4) 处
提示:
0 <= commands.length <= 10000
0 <= obstacles.length <= 10000
-30000 <= obstacle[i][0] <= 30000
-30000 <= obstacle[i][1] <= 30000
答案保证小于 2 ^ 31
class Solution {
public:
int robotSim(vector<int>& commands, vector<vector<int>>& obstacles) {
int x=0,y=0,d=0;//d:0 1 2 3 上,右,下,左
int i=0;
int max=INT_MIN;
set<vector<int> > s(obstacles.begin(),obstacles.end());
for(auto c:commands){
if(c==-2)
//d=(d+3)%4;
switch(d){
case 0:d=3;break;
case 1:d=0;break;
case 2:d=1;break;
case 3:d=2;break;
default:break;
}
else if(c==-1)
//d=(d+1)%4;
switch(d){
case 0:d=1;break;
case 1:d=2;break;
case 2:d=3;break;
case 3:d=0;break;
default:break;
}
else if(1<=c&&c<=9)
switch(d){
case 0:
i=0;
while(i++<c&&!s.count({x,y+1}))
++y;
break;
case 1:
i=0;
while(i++<c&&!s.count({x+1,y}))
++x;
break;
case 2:
i=0;
while(i++<c&&!s.count({x,y-1}))
--y;
break;
case 3:
i=0;
while(i++<c&&!s.count({x-1,y}))
--x;
break;
default:break;
}
max=max>(pow(x,2)+pow(y,2))?max:pow(x,2)+pow(y,2);
}
return max;
}
};
给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
示例 1:
输入: [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:
输入: [-1,-100,3,99] 和 k = 2
输出: [3,99,-1,-100]
解释:
向右旋转 1 步: [99,-1,-100,3]
向右旋转 2 步: [3,99,-1,-100]
说明:
尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。
要求使用空间复杂度为 O(1) 的 原地 算法。
知识点
1. c++中的reverse函数,格式为reverse(&想要反转的起始元素,&想要反转的最后一个元素+1)。
2. 学到了(i+k)%size(nums)。
········作用1:当k要求旋转好几轮时,可通过%将其化简为只旋转1轮。
········作用2:通过(i+k)%,可直接获取元素旋转之后的位置
class Solution {
public:
void rotate(vector<int>& nums, int k) {
//采用反转
int length=size(nums);
k%=size(nums);
reverse(&nums[0],&nums[length]);
reverse(&nums[0],&nums[k]);
reverse(&nums[k],&nums[length]);
}
void rotate2(vector<int>& nums, int k) {
//外层循环用来决定向右旋转次数
for(int i=0;i<k%size(nums);i++){
int tmp;
tmp=nums[size(nums)-1];
for(int j=size(nums)-1;j>0;j--){
nums[j]=nums[j-1];
}
nums[0]=tmp;
}
}
void rotate3(vector<int>& nums, int k){
//采用双数组(这样不满足O(1))
int* a=new int [size(nums)];
for(int i=0;i<size(nums);i++){
a[(i+k)%size(nums)]=nums[i];
}
for(int i=0;i<size(nums);i++){
nums[i]=a[i];
}
}
};
给你一个 m 行 n 列的二维网格 grid 和一个整数 k。你需要将 grid 迁移 k 次。
每次「迁移」操作将会引发下述活动:
位于 grid[i][j] 的元素将会移动到 grid[i][j + 1]。
位于 grid[i][n - 1] 的元素将会移动到 grid[i + 1][0]。
位于 grid[m - 1][n - 1] 的元素将会移动到 grid[0][0]。
请你返回 k 次迁移操作后最终得到的 二维网格。
示例 1:
输入:grid = [[1,2,3],[4,5,6],[7,8,9]], k = 1
输出:[[9,1,2],[3,4,5],[6,7,8]]
示例 2:
输入:grid = [[3,8,1,9],[19,7,2,5],[4,6,11,10],[12,0,21,13]], k = 4
输出:[[12,0,21,13],[3,8,1,9],[19,7,2,5],[4,6,11,10]]
示例 3:
输入:grid = [[1,2,3],[4,5,6],[7,8,9]], k = 9
输出:[[1,2,3],[4,5,6],[7,8,9]]
提示:
1 <= grid.length <= 50
1 <= grid[i].length <= 50
-1000 <= grid[i][j] <= 1000
0 <= k <= 100
class Solution {
public:
vector<vector<int>> shiftGrid(vector<vector<int>>& grid, int k) {
vector<int> v;
for(auto i:grid)//二维转一维
for(auto j:i)
v.push_back(j);
int size=v.size();
k=k%size;
reverse(&v[0],&v[size]);//三次反转完成一维右移
reverse(&v[0],&v[k]);
reverse(&v[k],&v[size]);
size=0;
for(auto &i:grid)//二维转一维
for(auto &j:i)
j=v[size++];
return grid;
}
};
给你一个字符串 s,它仅由字母 'a' 和 'b' 组成。每一次删除操作都可以从 s 中删除一个回文 子序列。
返回删除给定字符串中所有字符(字符串为空)的最小删除次数。
「子序列」定义:如果一个字符串可以通过删除原字符串某些字符而不改变原字符顺序得到,那么这个字符串就是原字符串的一个子序列。
「回文」定义:如果一个字符串向后和向前读是一致的,那么这个字符串就是一个回文。
示例 1:
输入:s = "ababa"
输出:1
解释:字符串本身就是回文序列,只需要删除一次。
示例 2:
输入:s = "abb"
输出:2
解释:"abb" -> "bb" -> "".
先删除回文子序列 "a",然后再删除 "bb"。
示例 3:
输入:s = "baabb"
输出:2
解释:"baabb" -> "b" -> "".
先删除回文子序列 "baab",然后再删除 "b"。
示例 4:
输入:s = ""
输出:0
提示:
0 <= s.length <= 1000
s 仅包含字母 'a' 和 'b'
- 审题:abcaaaaaaa
- 子序列:顺序取出,不一定是连续的,aa是,
- 字串/子字符串:必须是连续的,abc是,aa不是
class Solution {
public:
int removePalindromeSub(string s) {
if(s.empty())return 0;
for(int i=0;i<s.size()/2;++i)
if(s[i]!=s[s.size()-1-i])
return 2;
return 1;
}
};