概述
1、独一无二的出现次数(LC 1207)
给你一个整数数组 arr,请你帮忙统计数组中每个数的出现次数。
如果每个数的出现次数都是独一无二的,就返回 true;否则返回 false。
示例
示例 1:
输入:arr = [1,2,2,1,1,3]
输出:true
解释:在该数组中,1 出现了 3 次,2 出现了 2 次,3 只出现了 1 次。没有两个数的出现次数相同。
示例 2:
输入:arr = [1,2]
输出:false
示例 3:
输入:arr = [-3,0,1,-3,1,1,1,-3,10,0]
输出:true
代码
间接数组计算出现次数, 在对出现次数排序, 判断是否出现重复。
int cmp(const void *a,const void *b){
return *(int*)a - *(int*)b;
}
bool uniqueOccurrences(int* arr, int arrSize){
//1、快排 + 比较 记录出现次数, 最后比较
//2、声明 N 个空间,记录出现次数 模拟 Hash 表
//采用快排 + 比较 的方法
qsort(arr,arrSize,sizeof(int),cmp);
int * nums = malloc(sizeof(int)*arrSize);
//初始化赋值 初始为 1
int i;
for(i = 0;i < arrSize;i++) nums[i] = 1;
//比较
int cur = 0,tag = 0;
for(i = 1;i < arrSize;i++,cur++){
if(arr[cur] == arr[i]){
nums[tag]++;
continue;
}
tag++;
}
tag += 1; //少加了一次, 因为比较的是下标
//在判断 nums 数组是否重复
qsort(nums,tag,sizeof(int),cmp);
cur = nums[0];
cur = 0;
for(i = 1;i < tag;i++,cur++){
//printf("%d ",nums[i]);
if(nums[cur] == nums[i])
return false;
}
return true;
}
2、玩筹码(LC 1217)
示例
数轴上放置了一些筹码,每个筹码的位置存在数组 chips 当中。
你可以对 任何筹码 执行下面两种操作之一(不限操作次数,0 次也可以):
将第 i 个筹码向左或者右移动 2 个单位,代价为 0。
将第 i 个筹码向左或者右移动 1 个单位,代价为 1。
最开始的时候,同一位置上也可能放着两个或者更多的筹码。
返回将所有筹码移动到同一位置(任意位置)上所需要的最小代价。
示例
示例 1:
输入:chips = [1,2,3]
输出:1
解释:第二个筹码移动到位置三的代价是 1,第一个筹码移动到位置三的代价是 0,总代价为 1。
示例 2:
输入:chips = [2,2,2,3,3]
输出:2
解释:第四和第五个筹码移动到位置二的代价都是 1,所以最小总代价为 2。
代码
1.首先分析发现:偶数位置转移到任意偶数位置代价为0,同理奇数位置转移到任意奇数位置代价也为0;
2.其次,我们简化筹码位置,将所有偶数集中到2X位置,所有奇数集中到2X+1(或2X-1)位置;
3.要想代价最小,就是移动数量最小的集合。
4.综合分析,发现实际上就是统计奇数和偶数的个数,取小者。
时间复杂度O(n),空间复杂度O(1)。
int minCostToMoveChips(int* chips, int chipsSize){
int odd = 0, even = 0;
for(int i = 0; i < chipsSize; i++)
{
if(chips[i]%2)
odd++;
else
even++;
}
return (odd <= even)? odd: even;
}
3、距离顺序排列矩阵单元格(LC 1030)
给出 R 行 C 列的矩阵,其中的单元格的整数坐标为 (r, c),满足 0 <= r < R 且 0 <= c < C。
另外,我们在该矩阵中给出了一个坐标为 (r0, c0) 的单元格。
返回矩阵中的所有单元格的坐标,并按到 (r0, c0) 的距离从最小到最大的顺序排,其中,两单元格(r1, c1) 和 (r2, c2) 之间的距离是曼哈顿距离,|r1 - r2| + |c1 - c2|。(你可以按任何满足此条件的顺序返回答案。)
示例
示例 1:
输入:R = 1, C = 2, r0 = 0, c0 = 0
输出:[[0,0],[0,1]]
解释:从 (r0, c0) 到其他单元格的距离为:[0,1]
示例 2:
输入:R = 2, C = 2, r0 = 0, c0 = 1
输出:[[0,1],[0,0],[1,1],[1,0]]
解释:从 (r0, c0) 到其他单元格的距离为:[0,1,1,2]
[[0,1],[1,1],[0,0],[1,0]] 也会被视作正确答案。
示例 3:
输入:R = 2, C = 3, r0 = 1, c0 = 2
输出:[[1,2],[0,2],[1,1],[0,1],[1,0],[0,0]]
解释:从 (r0, c0) 到其他单元格的距离为:[0,1,1,2,2,3]
其他满足题目要求的答案也会被视为正确,例如 [[1,2],[1,1],[0,2],[1,0],[0,1],[0,0]]。
代码
存放距离 + 排序
int r0, c0;
//比较函数, 根据 当前点到目标点的哈曼顿距离 返回比较结果
int cmp(void* _a, void* _b) {
int *a = *(int**)_a, *b = *(int**)_b;
return fabs(a[0] - r0) + fabs(a[1] - c0) - fabs(b[0] - r0) - fabs(b[1] - c0);
}
int** allCellsDistOrder(int rows, int cols, int rCenter, int cCenter, int* returnSize, int** returnColumnSizes){
//计算二维矩阵距离 点 (r0,c0) 的距离并保存
//定义间接数组存放保存数据
r0 = rCenter, c0 = cCenter; //修改参数名便于计算
int length = rows * cols; //数组空间大小
int ** nums = malloc(sizeof(int*) * length); //一维数组存放结果
*returnColumnSizes = malloc(sizeof(int) * length);
for (int i = 0; i < length; i++) {
(*returnColumnSizes)[i] = 2; //返回的数组大小每列 = 2
nums[i] = malloc(sizeof(int) * 2); //为结果数组分配空间
}
int tag = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
nums[tag][0] = i;
nums[tag][1] = j;
tag++;
}
}
*returnSize = tag;
qsort(nums, length, sizeof(int*), cmp);
return nums;
}
4、分糖果(LC 1103)
排排坐,分糖果。
我们买了一些糖果 candies,打算把它们分给排好队的 n = num_people 个小朋友。
给第一个小朋友 1 颗糖果,第二个小朋友 2 颗,依此类推,直到给最后一个小朋友 n 颗糖果。
然后,我们再回到队伍的起点,给第一个小朋友 n + 1 颗糖果,第二个小朋友 n + 2 颗,依此类推,直到给最后一个小朋友 2 * n 颗糖果。
重复上述过程(每次都比上一次多给出一颗糖果,当到达队伍终点后再次从队伍起点开始),直到我们分完所有的糖果。注意,就算我们手中的剩下糖果数不够(不比前一次发出的糖果多),这些糖果也会全部发给当前的小朋友。
返回一个长度为 num_people、元素之和为 candies 的数组,以表示糖果的最终分发情况(即 ans[i] 表示第 i 个小朋友分到的糖果数)。
示例
示例 1:
输入:candies = 7, num_people = 4
输出:[1,2,3,1]
解释:
第一次,ans[0] += 1,数组变为 [1,0,0,0]。
第二次,ans[1] += 2,数组变为 [1,2,0,0]。
第三次,ans[2] += 3,数组变为 [1,2,3,0]。
第四次,ans[3] += 1(因为此时只剩下 1 颗糖果),最终数组变为 [1,2,3,1]。
示例 2:
输入:candies = 10, num_people = 3
输出:[5,2,3]
解释:
第一次,ans[0] += 1,数组变为 [1,0,0]。
第二次,ans[1] += 2,数组变为 [1,2,0]。
第三次,ans[2] += 3,数组变为 [1,2,3]。
第四次,ans[0] += 4,最终数组变为 [5,2,3]。
代码
简单迭代 模拟发糖
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* distributeCandies(int candies, int num_people, int* returnSize){
*returnSize = num_people;
int * nums = malloc(sizeof(int) * num_people);
int i = 0;
//为数组赋值
for(i = 0;i < num_people;i++)
nums[i] = 0;
int n = 1;
while(candies){
for(i = 0;i < num_people;i++){
//printf("%d %d ",n,i);
if(candies > n){
nums[i] += n;
candies -= n;
}
else{
nums[i] += candies;
candies = 0;
}
n++;
}
}
return nums;
}
5、IP 地址无效化(LC 1108)
给你一个有效的 IPv4 地址 address,返回这个 IP 地址的无效化版本。
所谓无效化 IP 地址,其实就是用 “[.]” 代替了每个 “.”。
示例
示例 1:
输入:address = "1.1.1.1"
输出:"1[.]1[.]1[.]1"
示例 2:
输入:address = "255.100.50.0"
输出:"255[.]100[.]50[.]0"
代码
替换即可
char * defangIPaddr(char * address){
//间接替换
char * change = malloc((strlen(address) + 10) * sizeof(char));
char str[4] = "[.]";
int i = 0,tag = 0,j;
for(i = 0;i < strlen(address);i++){
if(address[i] == '.'){
for(j = 0;j < 3;j++)
change[tag++] = str[j];
continue;
}
change[tag++] = address[i];
}
change[tag] = '