学习内容概况
目的:找编程和做题的手感
具体训练内容:万人千题第一阶段题库(思维导图),同时还有一些之前做过的题
练习后总结
具体细节之后补充为文字版,概况思维导图如下:
编程细节
- 位运算使用技巧
data<<1 = data*2
、data>>1 = data / 2
左移右移等于乘除2data & 1
可以判断是否为奇数data & (1<<i)
可以判断第i位是否为1
库函数适当使用
qsort
排序内容必须是数组
原型:
void qsort (void* base, size_t num, size_t size,
int (*compar)(const void*,const void*));
代码案例:
- 一维数组:
-
/* qsort example */ #include <stdio.h> /* printf */ #include <stdlib.h> /* qsort */ int values[] = { 40, 10, 100, 90, 20, 25 }; int compare (const void * a, const void * b) { return ( *(int*)a - *(int*)b ); } int main () { int n; qsort (values, 6, sizeof(int), compare); for (n=0; n<6; n++) printf ("%d ",values[n]); return 0; }
-
- 二维数组:
-
#include <stdio.h> /* printf */ #include <stdlib.h> /* qsort */ int cmp(const void *a,const void *b) { int *ap = *(int **)a; int *bp = *(int **)b; if(ap[0] == bp[0]) return ap[1] - bp[1]; else return ap[0] - bp[0]; } int cmp(const void *a, const void *b) { return ((int *)a)[0] - ((int *)b)[0]; } int main(){ int *b,**a; int n = 10; a = (int**)malloc(n*sizeof(int*));。 for(i=0;i<n;i++) { b = malloc(2*sizeof(int)); a[i] = b; } int c[10][2] = {0}; //赋值c qsort(a, n, sizeof(a[0]), cmp); qsort(c, n, sizeof(c[0]), cmp); for(i=0;i<n;i++) { free(a[i]); } free(a); }
-
- 结构体排序:
-
/* qsort example */ #include <stdio.h> /* printf */ #include <stdlib.h> /* qsort */ typedef struct node{ int x; int y; int z; }Node; //-> is prioer than (type) int cmp(const void *a, const void *b) { // return (Node *)a->x - (Node *)b->x; //wrong! // return ((Node *)a)->x - ((Node *)b)->x; //wrong! return (*(Node *)a).x - (*(Node *)b).x; //right } int main () { // get many Node things. qsort(a, n, sizeof(a[0]), cmp); }
-
解题模板
尽量通过总结和理解,将题目抽象为一类题目,并构建基础编程模板
看了题解的问题
-
- 快慢指针的经典使用
- 快指针先行探路,确定怎样的是符合规范的
- 慢指针是新的标准,用于接收符合条件的数据进行存储
- 符合条件的判断准则
- 快慢指针的经典使用
-
- 分情况讨论分析
- 判断条件的先后可能会影响复杂度
- 简化你的模型,不要陷入过度复杂的细节里,更多的简单重复的事情应该交给计算机做
- 有序一定要尝试二分法,即使无法实现严格的二分
- 分情况讨论分析
-
- 运用数学方法去分析数据和题目,分析数据的特征,并寻找规律
- 数学原理:n个正整数序列中的寻找没有出现过的最小的整数值,看数轴分析最多覆盖[1,n],所以要么在[1,n]之间,要么是n + 1
- 基于上述原理,可以使用+ - 号和abs将原数组作为hash表判断数据是否出现
-
- 确定适用的贪心策略,在遍历中迭代
- 记录迭代所需要的数据
解答汇总
编写的代码遵循以下规范:
- 代码使用C语言进行编写
- 代码尽量通过合适的变量名等方式提高可读性
- 尽量做到不使用注释能立马反应代码含义
- 代码中保留在LeetCode上调试代码的关键输出语句,不影响提交通过结果。
基础语法&数据处理&数据结构
位运算
136. 只出现一次的数字
int singleNumber(int* nums, int numsSize){
int res = 0;
while (numsSize--) {
printf("%d ",numsSize);
res ^= nums[numsSize];
}
return res;
}
面试题 16.01. 交换数字
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* swapNumbers(int* numbers, int numbersSize, int* returnSize){
*returnSize = numbersSize;
int *res = (int *)malloc(sizeof(int)*2);
res[0] = numbers[0] ^ numbers[1];
res[1] = numbers[1] ^ res[0];
res[0] = res[1] ^ res[0];
return res;
}
191. 位1的个数
int hammingWeight(uint32_t n) {
int res =0;
while (n) {
res += n & 1;
n >>= 1;
}
return res;
}
int hammingWeight(uint32_t n) {
int res =0;
while (n) {
n &= n - 1;
printf("%d ",n);
res++;
}
return res;
}
1486. 数组异或操作
int xorOperation(int n, int start){
int res = start;
while (n--) {
int num = start + 2 * n;
res ^= num;
}
return res ^ start;
}
1720. 解码异或后的数组
201. 数字范围按位与
int rangeBitwiseAnd(int left, int right){
int t = 0;
while (left != right) {
left >>= 1;
right >>= 1;
t++;
}
return left << t;
}
剑指 Offer 64. 求1+2+…+n
int sumNums(int n){
int A = n;
int B = n + 1;
int ans = 0;
//当b为偶数,a*b=2a * b/2;当n为奇数,a*b=(b-1)/2 * 2a+a
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
(B & 1) && (ans += A);
A <<= 1;
B >>= 1;
return ans >> 1;
}
理解整数型
1281. 整数的各位积和之差
int subtractProductAndSum(int n){
int mul = 1;
int sum = 0;
int num = 0;
while (n) {
num = n%10;
mul *= num;
sum += num;
n /=10;
}
return mul - sum;
}
1290. 二进制链表转整数
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
int getDecimalValue(struct ListNode* head){
struct ListNode *pNode = head;
int sum = 0;
while (pNode) {
sum = sum * 2 + pNode->val;
pNode = pNode->next;
}
return sum;
}
1342. 将数字变成 0 的操作次数
int numberOfSteps(int num){
int res = 0;
while (num) {
if (num & 1) {
res++;
num--;
continue;
}
res++;
num >>= 1;
}
return res;
}
1480. 一维数组的动态和
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* runningSum(int* nums, int numsSize, int* returnSize){
*returnSize = numsSize;
int *res = (int *) malloc(sizeof(int) * numsSize);
int i = 1;
res[0] = nums[0];
while (i < numsSize) {
res[i] = res[i - 1] + nums[i];
i++;
}
return res;
}
628. 三个数的最大乘积
int cmp(int *a, int *b) {
return *a - *b;
}
int maximumProduct(int* nums, int numsSize){
qsort(nums, numsSize, sizeof(int), cmp);
int res = (nums[numsSize-1] * nums[numsSize - 2] * nums[numsSize - 3]) >
(nums[0] * nums[1] *nums[numsSize - 1]) ?
(nums[numsSize-1] * nums[numsSize - 2] * nums[numsSize - 3]) :
(nums[0] * nums[1] *nums[numsSize - 1]);
return res;
}
1588. 所有奇数长度子数组的和
int sumOddLengthSubarrays(int* arr, int arrSize){
int res = 0;
int left = 0;
int right = 0;
int sum = 0;
while (left < arrSize){
sum += arr[right++];
if (((right - left) & 1)) {
res += sum;
}
if (right >= arrSize) {
left++;
right = left;
sum = 0;
}
}
return res;
}
485. 最大连续 1 的个数
int findMaxConsecutiveOnes(int* nums, int numsSize){
int cnt = 0;
int res = 0;
for (int i = 0; i < numsSize ; i++) {
res = cnt > res ? cnt : res;
cnt = cnt * nums[i] + nums[i];
}
return cnt > res ? cnt : res;
}
1822. 数组元素积的符号
int signFunc(int x) {
return x > 0 ? 1 : -1;
}
int arraySign(int* nums, int numsSize){
int mul = 1;
while (numsSize--) {
if (nums[numsSize] == 0)
return 0;
if (nums[numsSize] < 0)
mul *= (-1);
}
return mul;
}
1295. 统计位数为偶数的数字
int findNumbers(int* nums, int numsSize){
int res = 0;
while (numsSize--) {
int cnt = 1;
int num = nums[numsSize];
while (num/=10) {
cnt++;
}
if (cnt & 1) {
continue;
}
res++;
}
return res;
}
剑指 Offer 17. 打印从1到最大的n位数
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* printNumbers(int n, int* returnSize){
int size = 0;
while (n) {
size = size * 10 + 9;
n--;
}
*returnSize = size;
int *res = (int *) malloc(sizeof(int) * size);
while (size--) {
res[size] = size + 1;
}
return res;
}
剑指 Offer II 003. 前 n 个数字二进制中 1 的个数
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* countBits(int n, int* returnSize){
int *res = (int *)malloc(sizeof(int) * (n + 1));
*returnSize = n + 1;
res[0] = 0;
for (int i = 0; i <= n; i++) {
res[i] = res[i >> 1] + (i & 1);
}
return res;
}
字符串?
344. 反转字符串
void reverseString(char* s, int sSize){
for (int i = 0; i < sSize/2; i++) {
s[i] ^= s[sSize - 1 - i];
s[sSize - 1 - i] ^= s[i];
s[i] ^= s[sSize - 1 - i];
}
}
1662. 检查两个字符串数组是否相等
bool arrayStringsAreEqual(char ** word1, int word1Size, char ** word2, int word2Size){
int w1 = 0;
int w2 = 0;
int c1 = 0;
int c2 = 0;
while (w1 < word1Size && w2 < word2Size) {
int flag = 0;
if (word1[w1][c1] == '\0') {
w1++;
c1 = 0;
flag = 1;
}
if (word2[w2][c2] == '\0') {
w2++;
c2 = 0;
flag = 1;
}
if (flag) {
continue;
}
char ch1 = word1[w1][c1++];
char ch2 = word2[w2][c2++];
if (ch1 != ch2) {
return false;
}
}
if ((w1 != word1Size) || (w2 != word2Size)) {
return false;
}
return true;
}
1832. 判断句子是否为全字母句
bool checkIfPangram(char * sentence){
int hash[26] = {0};
int len = strlen(sentence);
while (len--) {
hash[sentence[len] - 'a']++;
}
for (int i = 0; i < 26; i++) {
if (hash[i] == 0) {
return false;
}
}
return true;
}
1684. 统计一致字符串的数目
int countConsistentStrings(char * allowed, char ** words, int wordsSize){
int res = 0;
int hash[26] = {0};
int len = strlen(allowed);
while (len--) {
hash[allowed[len] - 'a']++;
}
while (wordsSize--) {
char *tmp = words[wordsSize];
len = strlen(tmp);
while(len--) {
if (!hash[tmp[len] - 'a']) {
break;
}
}
if (len == -1) {
res++;
}
}
return res;
}
771. 宝石与石头
int getIndx(char x) {
return x - 'A' > 26 ? x - 'a' + 26 : x - 'A';
}
int numJewelsInStones(char * jewels, char * stones){
int numj = strlen(jewels);
int nums = strlen(stones);
int hash[54] = {0};
int res = 0;
while (nums--) {
int idx = getIndx(stones[nums]);
hash[idx]++;
}
while (numj--) {
int idx = getIndx(jewels[numj]);
res += hash[idx];
hash[idx] = 0;
}
return res;
}
2011. 执行操作后的变量值
int finalValueAfterOperations(char ** operations, int operationsSize){
int res = 0;
while (operationsSize--) {
operations[operationsSize][1] == '-' ?
res-- : res++;
}
return res;
}
剑指 Offer 58 - II. 左旋转字符串
char* reverseLeftWords(char* s, int n){
int len = strlen(s);
char *res = (char *)malloc(sizeof(char) * (len + 1));
res[len] = '\0';
for (int i = 0; i < len - n; i++) {
res[i] = s[n + i];
}
for (int i = 0; i < n; i++) {
res[len - n + i] = s[i];
}
return res;
}
面试题 01.01. 判定字符是否唯一
面试题 01.02. 判定是否互为字符重排
383. 赎金信
537. 复数乘法
void getVal (char *num, int *real1, int *virt1) {
int flag = 0;
int real = 0;
int virt = 0;
int minus = 1;
int len = strlen(num);
for (int i = 0; i < len; i++) {
if (num[i] == '+') {
flag = 1;
continue;
}
if (i > 0 && num[i] == '-') {
flag = -1;
continue;
} else if (num[i] == '-'){
minus = -1;
continue;
}
if (num[i] == 'i') {
break;
}
if (!flag) {
real = real * 10 + (num[i] - '0');
} else {
virt = virt * 10 + (num[i] - '0');
}
}
virt *=flag;
real *=minus;
printf("%d,%d", real, virt);
*real1 = real;
*virt1 = virt;
}
char * complexNumberMultiply(char * num1, char * num2){
int real1 = 0;
int real2 = 0;
int real = 0;
int virt1 = 0;
int virt2 = 0;
int virt = 0;
getVal (num1, &real1, &virt1);
getVal (num2,&real2, &virt2);
real = real1 * real2 - virt1 * virt2;
virt = real1 * virt2 + real2 * virt1;
char *res = (char *)malloc(sizeof(char) * 20);
sprintf(res, "%d+%di", real, virt);
return res;
}
1108. IP 地址无效化
char * defangIPaddr(char * address){
int len = strlen (address);
int newLen = len + 6;
char *res = (char *)malloc(sizeof(char) * newLen + 1);
res[newLen] = '\0';
while (len--) {
if (address[len] == '.') {
res[newLen-1] = ']';
res[newLen-2] = '.';
res[newLen-3] = '[';
newLen -= 3;
continue;
}
res[newLen - 1] = address[len];
newLen--;
}
return res;
}
基础数学
1925. 统计平方和三元组的数目
int countTriples(int n){
int a = 2;
int b = 3;
int res = 0;
for (a = 1; a < n; a++) {
for (b = 1; b < n; b++) {
int c = (int)sqrt(a * a + b * b + 1);
if (c <= n && (c * c == a * a + b * b)) {
res++;
}
}
}
return res;
}
2006. 差的绝对值为 K 的数对数目
int countKDifference(int* nums, int numsSize, int k){
int res = 0;
for (int i = 0; i < numsSize; i++) {
for (int j = i + 1; j < numsSize; j++) {
int judge = abs(nums[i] - nums[j]);
if (judge == k) {
res++;
}
}
}
return res;
}
1979. 找出数组的最大公约数
int findGCD(int* nums, int numsSize){
int max = nums[0];
int min = nums[0];
int res = 1;
for (int i = 1; i < numsSize; i++) {
max = max > nums[i] ? max : nums[i];
min = min < nums[i] ? min : nums[i];
}
return gcd (max, min);
}
1492. n 的第 k 个因子
int kthFactor(int n, int k){
int *elem = (int*) malloc(sizeof(int)*k);
int idx = 0;
for(int i = 1; i <= n && idx < k; i++) {
if (n % i == 0) {
elem[idx++] = i;
}
}
return idx < k ? -1 : elem[k-1];
}
剑指 Offer 57 - II. 和为s的连续正数序列
int** findContinuousSequence(int target, int* returnSize, int** returnColumnSizes) {
if (target < 2) {
return NULL;
}
int maxSize = (target + 1) / 2;
int** res = (int**)malloc(sizeof(int*) * maxSize);
*returnColumnSizes = (int*)malloc(sizeof(int) * maxSize);
int sizes = *returnColumnSizes;
int cnt = 0;
int i = 1;
int j = i;
int size = 1;
int sum = 0;
while (i < maxSize) {
if (sum < target) {
sum += j++;
size++;
}
if (sum > target) {
sum -= i++;
size--;
}
if (sum == target) {
(*returnColumnSizes)[cnt] = size - 1;
res[cnt] = (int*)malloc(sizeof(int) * (size - 1));
for (int z = 0; z < size - 1; z++) {
res[cnt][z] = i + z;
}
cnt++;
sum -= i++;
size--;
}
}
*returnSize = cnt;
return res;
}
面试题 08.05. 递归乘法
void swap(int *A, int *B) {
int t = *A;
if (*A < *B) {
*A = *B;
*B = t;
}
}
int multiply(int A, int B){
int sum = 0;
swap(&A, &B);
while(B) {
if (B & 1) {
sum += A;
}
B >>= 1;
if (B) A <<= 1;
}
return sum;
}
509. 斐波那契数
int fib(int n){
int f0 = 0;
int f1 = 1;
int fn = f0 + f1;
while (n > 1) {
fn = f0 + f1;
f0 = f1;
f1 = fn;
n--;
}
if (n < 1) return f0;
return fn;
}
812. 最大三角形面积
double area(int* P, int* Q, int* R) {
return 0.5 * abs(P[0] * Q[1] + Q[0] * R[1] + R[0] * P[1]
-P[1] * Q[0] - Q[1] * R[0] - R[1] * P[0]);
}
double largestTriangleArea(int** points, int pointsSize, int* pointsColSize){
double res = 0;
for (int i= 0; i < pointsSize - 2; i++) {
for (int j = i + 1; j < pointsSize - 1 ; j++) {
for (int z = j + 1; z < pointsSize; z++) {
double size = area (points[i], points[j], points[z]);
res = res > size? res : size;
}
}
}
return res;
}
进制理解与运算
504. 七进制数
char * convertToBase7(int num){
int resDec = 0;
int ifMinus = num >= 0 ? 0 : 1;
num = abs(num);
int cnt = 0;
int cal = num;
if (num == 0) {
cnt = 1;
}
while (cal) {
cal /= 7;
cnt++;
}
cnt = cnt + ifMinus + 1;
char *res = (char *) malloc(sizeof(char) * (cnt--));
if (ifMinus) {
res[0] = '-';
}
res[cnt--] = '\0';
while (cnt >= ifMinus) {
res[cnt--] = '0' + num % 7;
printf("%d", cnt + 1);
num /= 7;
}
return res;
}
405. 数字转换为十六进制数
char getHexChar(int num) {
switch (num) {
case 0:
return '0';
case 1:
return '1';
case 2:
return '2';
case 3:
return '3';
case 4:
return '4';
case 5:
return '5';
case 6:
return '6';
case 7:
return '7';
case 8:
return '8';
case 9:
return '9';
case 10:
return 'a';
case 11:
return 'b';
case 12:
return 'c';
case 13:
return 'd';
case 14:
return 'e';
case 15:
return 'f';
}
return '0';
}
char * toHex(int num){
char *res = (char*)malloc(sizeof(char) * 9);
unsigned int cal = (unsigned int) num;
if (num == 0) {
res[0] = '0';
res[1] = '\0';
return res;
}
int idx = 0;
while (cal) {
idx++;
cal /= 16;
}
cal = (unsigned int) num;
res[idx] = '\0';
while (idx--) {
res[idx] = getHexChar(cal % 16);
cal /= 16;
}
return res;
}
1837. K 进制表示下的各位数字总和
int sumBase(int n, int k){
int res = 0;
while (n) {
res += n%k;
n /= k;
}
return res;
}
190. 颠倒二进制位
uint32_t reverseBits(uint32_t n) {
uint32_t res = 0;
uint32_t t = (uint32_t)(-1);
while (t) {
res = (res << 1) + (n & 1);
n >>= 1;
t >>= 1;
}
return res;
}
258. 各位相加
int addDigits(int num){
int res = 0;
while (num) {
res += num % 10;
num = num / 10;
if (!num && res / 10) {
num = res;
res = 0;
}
}
return res;
}
理解数组
860. 柠檬水找零
1512. 好数对的数目
int numIdenticalPairs(int* nums, int numsSize){
int res = 0;
for (int i = 0; i < numsSize; i++) {
for (int j = i + 1; j < numsSize; j++) {
if (nums[i] == nums[j]) {
res++;
}
}
}
return res;
}
217. 存在重复元素
int cmp(int *a, int *b){
return *a - *b;
}
bool containsDuplicate(int* nums, int numsSize){
qsort(nums, numsSize, sizeof(int), cmp);
for(int i = 0; i < numsSize - 1; i++) {
if (nums[i] == nums[i + 1]) {
return true;
}
}
return false;
}
27. 移除元素
int removeElement(int* nums, int numsSize, int val){
int newIdx = 0;
int idx = 0;
for(; idx < numsSize; idx++) {
if (nums[idx] == val) {
continue;
}
if (nums[idx] != val) {
nums[newIdx++] = nums[idx];
}
}
return newIdx;
}
26. 删除有序数组中的重复项
int removeDuplicates(int* nums, int numsSize){
int fast = 1;
int slow = 0;
if(numsSize <= 1) {
return numsSize;
}
for (; fast < numsSize; fast++) {
if (nums[fast] != nums[fast -1]) {
nums[slow + 1] = nums[fast];
slow++;
}
}
return slow + 1;
}
1863. 找出所有子集的异或总和再求和
int subsetXORSum(int* nums, int numsSize){
int res = 0;
int xor = 0;
for (int i = 0; i < numsSize; i++){
res += nums[i];
xor ^= nums[i];
}
res += xor;
for (int i = 0; i < numsSize; i++) {
res += xor ^ nums[i];
}
return res;
}
1365. 有多少小于当前数字的数字
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* smallerNumbersThanCurrent(int* nums, int numsSize, int* returnSize){
int *res = (int *)malloc(sizeof(int) * numsSize);
memset(res, 0, sizeof(int) * numsSize);
*returnSize = numsSize;
int hash[101] = {0};
for (int i = 0; i < numsSize; i++) {
hash[nums[i]]++;
}
for (int i = 0; i < numsSize; i++) {
int val = nums[i];
while (val--) {
res[i] += hash[val];
}
}
return res;
}
1929. 数组串联
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* getConcatenation(int* nums, int numsSize, int* returnSize){
int len = numsSize;
*returnSize = 2 * len;
int *res = (int *) malloc(sizeof(int) * 2 * len);
while(len--) {
res[len] = nums[len];
res[len + numsSize] = nums[len];
}
return res;
}
1464. 数组中两元素的最大乘积
int maxProduct(int* nums, int numsSize){
int biggest;
int second;
int i;
if (numsSize < 2) {
return 0;
}
biggest = nums[0] > nums[1] ? nums[0] : nums[1];
second = nums[0] > nums[1] ? nums[1] : nums[0];
for (i = 2; i < numsSize ; i++) {
if (nums[i] > biggest) {
second = biggest;
biggest = nums[i];
} else if (nums[i] > second) {
second = nums[i];
}
}
return (biggest-1) * (second-1);
}
414. 第三大的数
//堆排序
void swap(int *nums,int i,int j){
int t=nums[i];
nums[i]=nums[j];
nums[j]=t;
}
void MaxHeapify(int *nums,int index,int numsSize){ //维护大根堆
int lchild=2*index,rchild=2*index+1;
int max=index;
if(lchild<numsSize&&nums[lchild]>nums[max])
max=lchild;
if(rchild<numsSize&&nums[rchild]>nums[max])
max=rchild;
if(index!=max){
swap(nums,index,max);
MaxHeapify(nums,max,numsSize);
}
}
void MaxHeap(int *nums,int numsSize){ //建堆
for(int i=numsSize/2;i>=0;i--){
MaxHeapify(nums,i,numsSize);
}
}
int thirdMax(int* nums, int numsSize){
MaxHeap(nums,numsSize); //建堆
int count=1,ans=nums[0],size=numsSize;
int max=ans;
while(count<3){
swap(nums,0,size-1);
--size;
if(size<1)
return max; //不够3次
MaxHeapify(nums,0,size); //维护大根堆
if(ans!=nums[0]){
++count;
ans=nums[0];
}else{
continue;
}
}
return nums[0];
}
链表の本质
面试题 02.03. 删除中间节点
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
void deleteNode(struct ListNode* node) {
struct ListNode* del = node->next;
node->val = node->next->val;
node->next = node->next->next;
free(del);
}
剑指 Offer 18. 删除链表的节点
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* deleteNode(struct ListNode* head, int val){
struct ListNode *dumHead = (struct ListNode *)malloc(sizeof(struct ListNode));
dumHead->next = head;
struct ListNode *pre = head;
struct ListNode *later = dumHead;
while (pre) {
if (pre->val == val) {
later->next = pre->next;
break;
}
pre = pre->next;
later = later->next;
}
free(pre);
return dumHead->next;
}
树の递归理解
144. 二叉树的前序遍历
94. 二叉树的中序遍历
589. N 叉树的前序遍历
LCP 44. 开幕式焰火
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
int dfs (int res, int * hash, struct TreeNode* root) {
if (!root) {
return res;
}
if (hash[root->val] == 0) {
//printf("%d ", hash[root->val]);
hash[root->val] = 1;
++res;
}
res = dfs(res, hash, root -> left);
res = dfs(res, hash, root -> right);
return res;
}
int numColor(struct TreeNode* root){
int res = 0;
int hash[1001] = {0};
res = dfs(res, hash, root);
return res;
}
剑指 Offer 27. 二叉树的镜像
剑指 Offer 55 - I. 二叉树的深度
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
int maxDepth(struct TreeNode* root){
if (!root) {
return 0;
}
return fmax(maxDepth(root -> left), maxDepth(root -> right)) + 1;
}
剑指 Offer 55 - II. 平衡二叉树
基础算法&思维
查找
剑指 Offer 04. 二维数组中的查找
33. 搜索旋转排序数组
int search(int* nums, int numsSize, int target){
int res;
int left = 0;
int right = numsSize - 1;
int mid = (left + right) / 2;
while (left <= right) {
printf ("%d, %d, %d\n", left, mid, right);
if (nums[mid] == target) {
return mid;
}
if (nums[left] == target) {
return left;
}
if (nums[right] == target) {
return right;
}
// left is a sorted array
if (nums[left] < nums[mid]) {
if (nums[mid] < target) {
left = mid + 1;
right -=1;
} else {
left += 1;
right -=1;
}
} else {
// right is sorted
if (nums[mid] > target) {
left += 1;
right = mid - 1;
} else {
left += 1;
right -=1;
}
}
mid = (left + right) / 2;
}
return -1;
}
153. 寻找旋转排序数组中的最小值
int findMin(int* nums, int numsSize){
int left = 0;
int right = numsSize - 1;
int mid = (left + right) / 2;
do {
///< when the graph is like ^V
if (nums[left] > nums[right]) {
///< narrow the border, follow the trend
left = nums[mid] > nums[left] ? mid : left;
right = nums[mid] < nums[right] ? mid : right;
mid = (left + right) / 2;
} else { ///< is like A
return nums[left];
}
} while (1 != (right - left)) ;
///< is like V
return nums[right];
}
int search(int* nums, int numsSize, int target){
int left = 0;
int right = numsSize - 1;
int mid = (left + right) / 2;
if (numsSize == 1) {
return (nums[0] == target) ? 0 : -1;
}
while (left <= right) {
if (nums[mid] == target) {
return mid;
}
if (nums[left] == target) {
return left;
}
if (nums[right] == target) {
return right;
}
if (nums[left] < nums[mid]) {
if (nums[left] < target && nums[mid] > target) {
left = left + 1;
right = mid - 1;
} else {
left = mid + 1;
right = right - 1;
}
} else {
if (nums[mid + 1] <= target && nums[right] > target) {
left = mid + 1;
right = right - 1;
} else {
left = left + 1;
right = mid - 1;
}
}
mid = (left + right) / 2;
}
return -1;
}
1302. 层数最深叶子节点的和
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
//int sum;
//int depth;
void dfs(struct TreeNode* root, int cur_depth, int max, int *sum)
{
if (root == NULL){
return;
}
if ((root->left == NULL) && (root->right == NULL) && (cur_depth == max)) {
*sum += root->val;
}
dfs(root->left, cur_depth + 1, max, sum);
dfs(root->right, cur_depth + 1, max, sum);
}
int maxDepth(struct TreeNode* root) {
if (!root){
return 0;
}
return 1 + fmax(maxDepth(root->left), maxDepth(root->right));
}
int deepestLeavesSum(struct TreeNode* root){
int sum = 0;
int max = maxDepth(root);
dfs(root, 1, max, &sum);
return sum;
}
剑指 Offer 11. 旋转数组的最小数字
int minArray(int* numbers, int numbersSize){
int low = 0;
int high = numbersSize - 1;
while (low < high) {
int pivot = low + (high - low) / 2;
if (numbers[pivot] < numbers[high]) {
high = pivot;
} else if (numbers[pivot] > numbers[high]) {
low = pivot + 1;
} else {
high -= 1;
}
}
return numbers[low];
}
41. 缺失的第一个正数
int firstMissingPositive(int* nums, int numsSize){
for (int i = 0; i < numsSize; i++) {
if (nums[i] <= 0) {
nums[i] = numsSize + 1;
}
}
for (int i = 0; i < numsSize; i++) {
if (abs(nums[i]) <= numsSize) {
if (nums[abs(nums[i]) - 1] > 0)
nums[abs(nums[i]) - 1] *= -1;
}
}
for (int i = 0; i < numsSize; i++) {
if(nums[i] > 0) {
return i + 1;
}
}
return numsSize + 1;
}
154. 寻找旋转排序数组中的最小值 II
int findMin(int* nums, int numsSize){
int left = 0;
int right = numsSize - 1;
while (right - left > 1) {
int mid = (left + right) / 2;
if (nums[left] > nums[right]) {
left = nums[mid] >= nums[left] ? mid : left;
right = nums[mid] <= nums[right] ? mid : right;
} else if (nums[left] == nums[right]) {
right--; ///< only deselect one
} else {
return nums[left];
}
}
return nums[left] < nums[right] ? nums[left] : nums[right];
}
排序
451. 根据字符出现频率排序
int getIdx(char x) {
if (x - 'A' >= 0){
return x - 'A' > 26 ? x - 'a' + 26 : x - 'A';
} else {
return x - '0' + 52;
}
}
char idx2char(int idx) {
return idx < 26 ? (char)(idx + 'A') :
idx < 52 ? (char)(idx - 26 + 'a') : (char)(idx - 52 + '0');
}
int cmp(const void *a, const void *b)
{
if (((int *)b)[1] != ((int *)a)[1]) {
return ((int *)b)[1] - ((int *)a)[1];
} else {
return ((int *)a)[0] - ((int *)a)[0];
}
}
char * frequencySort(char * s){
int len = strlen(s);
char *res = (char *)malloc(sizeof(char) * (len + 1));
int hash[62] = {0};
while (len--) {
hash[getIdx(s[len])]++;
}
int tmp[62][2] = {0};
for (int i = 0; i < 62; i++) {
int t = hash[i];
tmp[i][0] = i;
tmp[i][1] = t;
//printf("%d ", t);
}
qsort(tmp, 62, sizeof(tmp[0]), cmp);
len = 0;
for (int i = 0; i < 62; i++) {
int t = tmp[i][1];
if (t == 0) {
break;
}
while (t--) {
res[len++] = idx2char(tmp[i][0]);
}
}
res[len] = '\0';
return res;
}
912. 排序数组
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int cp(int *a, int *b) {
return *a - *b;
}
int* sortArray(int* nums, int numsSize, int* returnSize){
int *res = (int*) malloc (sizeof(int) * numsSize);
*returnSize = numsSize;
memcpy(res,nums,sizeof(int)*numsSize);
qsort(res,numsSize,sizeof(int),cp);
return res;
}
贪心
121. 买卖股票的最佳时机
int maxProfit(int* prices, int pricesSize){
int minPrice = 1e9;
int maxPro = 0;
for (int i = 0; i < pricesSize; i++){
maxPro = maxPro > (prices[i] - minPrice) ? maxPro : (prices[i] - minPrice);
minPrice = prices[i] < minPrice ? prices[i] : minPrice;
}
return maxPro;
}
还差得远呢!
关于之前刷题没有及时复习导致重新再看没有什么思路,以及群里一些同学发的稍微复杂一点的问题根本毫无思路的事。。。慢慢重刷ing
之前的题
659. 分割数组为连续子序列
322. 零钱兑换
204. 计数质数
169. 多数元素
98. 验证二叉搜索树
2. 两数相加
3. 无重复字符的最长子串
7. 整数反转
11. 盛最多水的容器
二分法
区间位移-蓝桥杯
数轴上有n个闭区间D1,…,Dn。其中区间Di用一对整数[ai, bi]来描述,满足ai < bi。
已知这些区间的长度之和至少有10000。所以,通过适当的移动这些区间,你总可以使得他们的“并”覆盖[0, 10000]——也就是说[0, 10000]这个区间内的每一个点都落于至少一个区间内。
你希望找一个移动方法,使得位移差最大的那个区间的位移量最小。
具体来说,假设你将Di移动到[ai+ci, bi+ci]这个位置。你希望使得max |ci| 最小。
枚举
n选m个的全排列
从n个当中选m个,有多少种排列呢? 请全输出
输入格式
输入n,m(1≤m≤n≤5)
输出格式
所有可能的排列,字典序
输入输出样例
输入
3 2 1
输出
12 13 21 23 31 32