
LeetCode 30天C语言挑战
1. 找出只出现了一次的数
ways1是正常的运算,将数组的每个元素都放在数组中遍历,遍历途中,如果有和自己相同的数,则count++,如果该数只出现了一次,则只能匹配到自己本身,count++只执行一次,此次遍历值为1,说明该数只出现了一次
ways2是通过全局进行异或运算,同0异1,精髓的思想在于两个相同的数进行异或运算后值为0(无论这两个数是直接异或还是间接异或,数组内所有数一起异或后剩下的数一定是只出现过一次的数,应为其他的数都两两抵消了)
#include<stdio.h>
int ways1(int* arr, int len) {
int i = 0, j = 0, count;
for (i = 0; i < len; i++) {
count = 0;
for (j = 0; j < len; j++) {
if (arr[i] == arr[j])
count++;
}
if (count == 1)
return arr[i];
}
return -1;
}
int ways2(int* arr, int len) {
int i, res = 0;
for (i = 0; i < len; i++) {
res ^= arr[i]; // ^异或运算,同 0 异 1
}
return res;
}
int main() {
int arr[] = { 1,2,2,4,1,4,9,8,8 };
int len = sizeof(arr) / sizeof(arr[0]);
printf("result = %d\n", ways1(arr, len));
printf("result = %d\n", ways2(arr, len));
system("pause");
return 0;
}
2. 判断一个数是否为快乐数
方法二,循环遍历后面所有数,直至遇到1或者4,遇到1则说明符合快乐数定义,4是后面循环遍历发现的规律,只要是不会遇到1的死循环,都会经过4,遇到4也会陷入不遇1的死循环,则说明不是快乐数
方法一,和思路一类似,只是巧妙的运用了“追赶思想”。
slow追上fast结束循环,此时有可能是后面陷入无限1循环,或者死循环撞上了
返回的是 判断 slow 是否为1 的bool值
#include <stdio.h>
#include <stdlib.h>
int bitSum(int n) {
int sum = 0, j;
while (n) {
j = n % 10;
sum += j * j;
n /= 10;
}
return sum;
}
int isHappyWay1(int n) {
int fast = n, slow = n;
do {
slow = bitSum(slow);
fast = bitSum(bitSum(fast));
printf("slow = %d, fast = %d\n",slow,fast);
} while (slow != fast);
return slow == 1;
}
void isHappyWay2(int n){
while (n != 1 && n != 4) // 之前输出发现规律,死循环必定经过4
{
n = bitSum(n);
int new_n = n;
printf("%-4d", new_n);
}
if (n == 1) printf("\nYES"); // 遇到1为快乐数
else printf("\n NO");
}
int main() {
int n;
scanf_s("%d", &n);
// isHappyWay2(n);
if (isHappyWay1(n)) printf("YES");
else printf("NO");
system("pause");
return 0;
}
3. 求一个数组内最大的一个片段的和
解析:见注解
#include<iostream>
#include<time.h>
using namespace std;
// 求一个数组内和最大的一个片段的和
int MaxSubArr_way1(int * arr, int size) {
//printf("i\tj\tsum\tmax\n");
int i, j, k, sum, max = arr[0];
for (i = 0; i < size; i++) {
for (j = i; j < size; j++) {
sum = 0;
for (k = i; k < j; k++) {
sum += arr[k];
}
max = max > sum ? max : sum;
//printf("%d\t%d\t%d\t%d\n", i, j, sum, max);
}
}
return max;
}
int MaxSubArr_way2(int* arr, int size) {
//printf("i\tj\tsum\tmax\n");
int i, j, k, sum, max = arr[0];
for (i = 0; i < size; i++) {
sum = 0;
for (j = i; j < size; j++) {
sum += arr[j]; // 范围扩大一位,但是和不需要再从头开始累加,只需要在上一次基础上再加上 arr[j]即可
max = max > sum ? max : sum;
//printf("%d\t%d\t%d\t%d\n", i, j, sum, max);
}
}
return max;
}
int main() {
int array1[] = { -2,1,-3,4,-1,2,1,-5,4 }, size1, size2, max1, max2;
int array2[] = { -3, 5, -7, 2, -6, 9, -4, 1, 0, -2, 7, -5, 3, -8, 6, -1, 4, -3, 8, -6, 10, -7, 5, -4, 2, 9, -3, 0, -1, 7, -5, 4 };
size1 = sizeof(array1) / sizeof(array1[0]);
size2 = sizeof(array2) / sizeof(array2[0]);
max2 = MaxSubArr_way2(array2, size2);
clock_t startTime, endTime;
float s_time;
startTime = clock(); // ---
for (int i = 0; i < 10000; i++) max1 = MaxSubArr_way1(array2, size2);
endTime = clock(); // ---
s_time = float(endTime - startTime) / CLOCKS_PER_SEC;
printf("MaxSubArr_way1 耗时 %f \n", s_time);
startTime = clock(); // ---
for (int i = 0; i < 10000; i++) max1 = MaxSubArr_way2(array2, size2);
endTime = clock(); // ---
s_time = float(endTime - startTime) / CLOCKS_PER_SEC;
printf("MaxSubArr_way2 耗时 %f \n", s_time);
printf("MaxSum_by MaxSubArr_way1() = %d\n", max1);
printf("MaxSum_by MaxSubArr_way2() = %d\n", max2);
system("pause");
return 0;
}
两方法运行时间对比:
4. 将某个数组的0元素都移到右边,非零都移到左边
交换法流程:
/*
交换法,遍历数组,如果某个元素为0,右边为非零,则交换位置
{ 1,0,4,0,9,0 } 0 1 2 3 4 5
{ 1,0,4,0,9,0 } -> { 1,4,0,0,9,0 } -> { 1,4,0,9,0,0 }
{ 1,4,0,9,0,0 } -> { 1,4,9,0,0,0 }
*/
交换法,遍历数组,如果某个元素为0,右边为非零,则交换位置
从交换规律上来看,有一点类似于冒泡排序,但是次数一定小于冒泡,
所以外层遍历arrSize次完全足够,当然也可以通过第三变量,通过第二层循环来判断是否迁移完成
#include<iostream>
using namespace std;
void arrPrint(int* arr, int arrSize) {
for (int j = 0; j < arrSize; j++) {
if (j == 0) printf("{ %d,", arr[0]);
else if (j < arrSize - 1) printf("%d,", arr[j]);
else printf("%d }\n", arr[arrSize - 1]);
}
return;
}
// 将某个数组的0元素都移到右边,非零都移到左边
void moveZero(int* arr, int arrSize) {
for (int k = 0; k < arrSize; k++) {
for (int i = 0; i + 1 < arrSize; i++) {
if (arr[i] == 0 && arr[i + 1] != 0) {
int t = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = t;
}
}
}
// 打印输出
arrPrint(arr, arrSize);
return;
}
int main() {
int arr[] = { 1,0,4,0,9,0,88,23,99 };
moveZero(arr, sizeof(arr) / sizeof(arr[0]));
system("pause");
return 0;
}
5. 给出一个股票价格数组,求出最大利润
注意: 股票可以多次买卖,但是只有卖了上次的才能进行下次购买
方法一,递归法,先假设最后一天卖不卖,如果不卖的话,相当于最后一天可有可无
1) 假设最后一天不卖
[7, 1, 5, 3, 6, 4] => maxProfit(prices, 5) // 等价
2) 假设最后一天卖, 把所有最后一次买的情况都罗列出来,然后把此次和第一天的这个
范围递交出去重新考虑,最后归值都加到prifit上,最后判断那次利润最大,返回最大利润
[7, 1, 5, 3, 6] + (6, 4) => maxProfit(prices, 5) + (prices[5] - prices[4])
[7, 1, 5, 3] + (3, 4) => maxProfit(prices, 4) + (prices[5] - prices[3])
[7, 1, 5] + (5, 4) => maxProfit(prices, 3) + (prices[5] - prices[2])
[7, 1] + (1, 4) => maxProfit(prices, 2) + (prices[5] - prices[1])
[7] + (7, 4) => maxProfit(prices, 1) + (prices[5] - prices[0])
当价格数组长度为1的时候,max = 0
(利润最差为0,即使股票价格数组是递减,也可以通过不卖来避免负利润)
方法二,有点复杂,等有空再写解析
方法三,只比较相邻的两天,如果i天比i+1天的便宜,那就买,并计算利润差加到总和
[7, 1, 5, 3, 6, 4]
^ ^
为什么可以这样? (贪心)
代码:
#include<stdio.h>
#include<stdlib.h>
// 给出一个股票价格数组 [7, 1, 5, 3, 6, 4], 求出最大利润
// 注意: 股票可以多次买卖,但是只有卖了上次的才能进行下次购买
int maxProfit(int* prices, int pricesSize) {
if (pricesSize <= 1) return 0;
int profit;
int max = 0;
// 1)
profit = maxProfit(prices, pricesSize - 1);
if (profit > max) max = profit;
// 2)
for (int i = 1; i <= pricesSize - 1; i++) {
profit = maxProfit(prices, i) + prices[pricesSize - 1] - prices[i - 1];
if (profit > max) max = profit;
}
return max;
}
int maxProfitWay2(int* prices, int pricesSize) {
if (pricesSize <= 1) return 0;
int* profits = (int*)malloc((pricesSize + 1) * sizeof(int));
// 通过动态内存分配来实现变量定义数组长度
if (profits == NULL) {
fprintf(stderr, "Memory allocation filed\n");
return -1;
}
profits[1] = 0;
for (int k = 2; k <= pricesSize; k++) {
int profit;
int max = 0;
profit = profits[k - 1];
if (profit > max) max = profit;
for (int i = 1; i <= k - 1; i++) {
profit = profits[i] + prices[k - 1] - prices[i - 1];
if (profit > max) max = profit;
}
profits[k] = max;
}
int result = profits[pricesSize];
free(profits);
return result;
}
int maxProfitWay3(int* prices, int pricesSize) {
int sum = 0;
for (int i = 0; i + 1 < pricesSize; i++) {
if (prices[i] < prices[i + 1])
sum += prices[i + 1] - prices[i];
}
return sum;
}
int main() {
int prices[] = { 7, 1, 5, 3, 6, 4 };
int sz = sizeof(prices) / sizeof(prices[0]);
printf("最大利润为(maxProfit): %d\n", maxProfit(prices, sz));
printf("最大利润为(maxProfitWay2): %d\n", maxProfitWay2(prices, sz));
printf("最大利润为(maxProfitWay3): %d\n", maxProfitWay3(prices, sz));
system("pause");
return 0;
}
6. 给定一组字符串,将相同字母的异序词组合在一起
给定一组字符串,将相同字母的异序词组合在一起
Example
Input: ["eat", "tea", "tan", "ate", "nat", "bat"],
Output:
[
["ate", "eat", "tea"],
["nat", "tan"],
["bat"]
]
代码如下
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#pragma warning(disable : 4996)
int cmpChar(const void* a, const void* b) {
return *(const char*)a - *(const char*)b;
}
typedef struct {
char* original;
char* sorted;
} Pair;
int comPair(const void* a, const void* b) {
const Pair* pa = (const Pair*)a;
const Pair* pb = (const Pair*)b;
return strcmp(pa->sorted, pb->sorted);
}
char*** groupAnagrams(char** strs, int strsSize, int* returnSize, int** returnColumnSizes) {
// strs: ["eat", "tea", "tan", "ate", "nat", "bat"], strsSize: 6
Pair* pairs = malloc(sizeof(Pair) * strsSize);
for (int i = 0; i < strsSize; i++) {
char* sorted_str = malloc(sizeof(char) * (strlen(strs[i]) + 1));
strcpy(sorted_str, strs[i]);
qsort(sorted_str, strlen(strs[i]), sizeof(char), cmpChar);
pairs[i].original = strs[i];
pairs[i].sorted = sorted_str;
}
qsort(pairs, strsSize, sizeof(Pair), comPair);
char*** returnResult = NULL;
*returnSize = 0;
*returnColumnSizes = NULL;
for (int i = 0; i < strsSize; i++) {
if (i == 0 || strcmp(pairs[i].sorted, pairs[i - 1].sorted) != 0) {
int lastGroupIndex = *returnSize;
returnResult = realloc(returnResult, sizeof(char**) * (*returnSize + 1));
returnResult[lastGroupIndex] = malloc(sizeof(char*) * 1);
returnResult[lastGroupIndex][0] = pairs[i].original;
(*returnSize)++;
*returnColumnSizes = realloc(*returnColumnSizes, sizeof(int) * (*returnSize));
(*returnColumnSizes)[lastGroupIndex] = 1;
}
else {
int lastGroupIndex = *returnSize - 1;
int lastGroupSize = (*returnColumnSizes)[lastGroupIndex];
returnResult[lastGroupIndex]
= realloc(returnResult[lastGroupIndex], sizeof(char*)* (lastGroupSize + 1));
returnResult[lastGroupIndex][lastGroupSize] = pairs[i].original;
(*returnColumnSizes)[lastGroupIndex] = lastGroupSize + 1;
}
}
return returnResult;
}
int main() {
char* input[] = { "eat", "tea", "tan", "ate", "nat", "bat","wxy","xyw"};
int strsSize = sizeof(input) / sizeof(input[0]);
int returnSize;
int* returnColumnSizes;
char*** result = groupAnagrams(input, strsSize, &returnSize, &returnColumnSizes);
printf("[\n");
for (int i = 0; i < returnSize; i++) {
printf(" [");
for (int j = 0; j < returnColumnSizes[i]; j++) {
printf("\"%s\"", result[i][j]);
if (j < returnColumnSizes[i] - 1) {
printf(", ");
}
}
printf("]\n");
}
printf("]\n");
// Free allocated memory for result and returnColumnSizes
for (int i = 0; i < returnSize; i++) {
free(result[i]);
}
free(result);
free(returnColumnSizes);
system("pause");
return 0;
}
输出测试:
7. 数组内的数,值+1 后在原数组内是否还存在,记录存在的数的个数
示例与分析
Example 1
Input: arr =[1, 1, 3, 3, 5, 5, 7, 7]
Output: 0
Explanation: No numbers are counted, cause there's no 2,4,6,or 8 in arr
Example 2
Input: arr = [1, 3, 2, 3, 5, 0]
Output: 3
Explanation: 0, 1 and 2 are counted cause 1, 2 and 3 are in arr
way1: 正常的思维就是两层for循环遍历的做法,这里就不使用这种方法了
way2: 用表来记录, 例如 hashList[1002] = 0; 遍历赋值hashList[arr[i]] = 1
if(hashList[arr[i]+1]) == 1; count++;
ways3: 通过排序来做,排序后,如果 arr[i] != arr[i+1] 且 arr[i+1] - arr[i] == 1,
则将前面相同数的个数加到count里面,前面相同的数用numbers统计,numbers在遇到不同数时重置为1
代码:
#include<bits/stdc++.h>
using namespace std;
int cmp(const void* a, const void* b) {
return *(const int*)a - *(const int*)b;
}
int main() {
int arr[] = { 1,1,2,2,5,5,7,7 };
//int arr[] = { 6,9,3,6,11,8,34,2 };
int arrSize = sizeof(arr) / sizeof(arr[0]);
qsort(arr, arrSize, sizeof(int), cmp);
//for (int i = 0; i < arrSize; i++) {
// printf("%d ",arr[i]);
//}
int count = 0;
int number = 1;
for (int i = 1; i < arrSize; i++) {
if (arr[i] != arr[i - 1]) {
if (arr[i] == arr[i - 1] + 1) {
count += number;
}
number = 1;
}
else {
number++;
}
}
cout << count << endl;
system("pause");
return 0;
}
- 感谢你赐予我前进的力量