1.19 LeetCode总结(基本算法)_数学类

本文深入探讨了多种编程技巧和算法,包括罗马数字与整数转换、回文串判断、矩阵操作、数字位运算等,提供了详尽的代码示例和优化思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

编程总结

每每刷完一道题后,其思想和精妙之处没有地方记录,本篇博客用以记录刷题过程中的遇到的算法和技巧

13. 罗马数字转整数

罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。
字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:
I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。

在这里插入图片描述

struct hash
{
	int interger;
	char roman;
};
// 哈希表
struct hash Hash[13] = {
	1000, 'M',
	500,  'D',
	100,  'C',
	50,   'L',
	10,   'X',
	5,    'V',
	1,    'I'
};
int charToInt(char c)
{
	for (int i = 0; i < 7; i++)
	{
		if (Hash[i].roman == c) {
			return Hash[i].interger;
		}
	}
	return 0;
}
int romanToInt(char * s)
{
	int len = strlen(s);
	int value = 0;
	int cur, next;
	for (int i = 0; i < len - 1; i++)  // 先计算 [0, len-1)
	{
		cur = charToInt(s[i]);
		next = charToInt(s[i + 1]);
		value = (cur < next) ? value - cur : value + cur;  // 小技巧,如果cur < next 则减掉cur
	}
	value += charToInt(s[len - 1]);    // 补上 len-1
	return value;
}

两种方法都使用哈希表来实现。

散列表(Hash table,也叫哈希表),是根据键(Key)而直接访问在内存存储位置的数据结构。也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度。这个映射函数称做散列函数,存放记录的数组称做散列表

整数转罗马,整数可以根据更为详细的哈希表来转换,但罗马转数字不行,得挨个查找,因为,仅看字符无法知道是需要减的情况还是增的情况,所以上下都使用了哈希表,但其表是不一样的。

struct hash
{
    int interger;
    char roman[4];
}Hash[13] = {       // 这也是一种初始化的方法
    1000, "M",
    900,  "CM", 
    500,  "D", 
    400,  "CD",
    100,  "C",
    90,   "XC",
    50,   "L",
    40,   "XL",
    10,   "X",
    9,    "IX",
    5,    "V",
    4,    "IV",
    1,    "I",
};

char *intToRoman(int num) {
	char *cRoman = NULL;
	unsigned short uIndex = 0;
    cRoman = (char *)malloc(16 *sizeof(char));;
    memset(cRoman, 0, 16);

	for (uIndex = 0; uIndex <= (13 - 1); uIndex++)
	{
		while (num >= Hash[uIndex].interger)
		{
			num = num - Hash[uIndex].interger;
			strcat(cRoman, Hash[uIndex].roman); // 注意此时的Hash和之前的不一样,更为详细
		}
	}

	return cRoman;
}

注意下面直接分配栈空间地址回去在leetcode是不允许的,会报错,应该使用上面的 malloc 使用堆地址空间:

char *intToRoman(int num){
    char cRoman[16] = {0x0};   // 申请栈空间
    unsigned short uIndex = 0;

    for(uIndex = 0; uIndex <= (13-1); uIndex++)
    {
        while(num >= Hash[uIndex].interger)
        {
            num = num - Hash[uIndex].interger;
            strcat_s(cRoman, Hash[uIndex].roman); // 注意此时的Hash和之前的不一样,更为详细
        }
    }

    return cRoman;              // 返回栈空间
}

409. 最长回文串

给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串。
在构造过程中,请注意区分大小写。比如 “Aa” 不能当做一个回文字符串。

#define G_LENGTH  57                     //  ASCII编码中,A~z共有57个字符
// 65~90为26个大写英文字母,97~122号为26个小写英文字母
int longestPalindrome(char *s)
{
    int g_string[G_LENGTH] = {0};
	int length = strlen(s);
	int value = 0;
	int ans   = 0;

	memset(g_string, 0, G_LENGTH);

	for(int i = 0; i < length; i++) {
		g_string[(s[i] - 'A') % 57]++;   // 哈希存储
	}

	for(int j = 0; j < G_LENGTH; j++) {
		if (g_string[j] !=0 ) {
			value = g_string[j];         // 每个字符出现的次数
			ans = ans + value/2 * 2;     // 左右都出现一次 v / 2
			if (value % 2 == 1 && ans % 2 == 0) { // 发现第一个出现次数为奇数加1,其他情况不加
				++ans;
			}
		}
	}

	return ans;
}

剑指 Offer 62. 圆圈中最后剩下的数字

  1. 0,1,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。
    例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。
// 递归
int lastRemaining(int n, int m){
    return f(n, m);
}
int f(int n, int m) 
{
    if (n == 1)
        return 0;
    int x = f(n - 1, m);
    return (m + x) % n;
}

// 另一种方法
int lastRemaining(int n, int m){
    if (n == 1) {  
        return 0;
	}
    int ans = 0;
    for (int i = 2; i <= n ;i++) {
        ans = (ans + m) % i;
    }
    
    return ans;
}

推导公式参考:https://leetcode-cn.com/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof/solution/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-by-lee/

矩阵相乘:
https://blog.youkuaiyun.com/qq_41649694/article/details/81432663

136. 只出现一次的数字

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

int singleNumber(int *nums, int numsSize) 
{
	int i = 0; 
	int tmp = 0;
	// 任何数和 00 做异或运算,结果仍然是原来的数,即 a \oplus 0 = aa⊕0 = a
	// 任何数和其自身做异或运算,结果是 00,即 a \oplus a = 0a⊕a = 0
	// 异或运算满足交换律和结合律,即 a \oplus b \oplus a = b 
	for (i = 0; i < numsSize; i++) { // 数组中两两出现的数字都会异或成原来的数,剩下的0和单独出现数字异或得数字本身
		tmp = tmp ^ nums[i];
	}

	return tmp;
}

680. 验证回文字符串 Ⅱ

给定一个非空字符串 s,最多删除一个字符。判断是否能成为回文字符串

// 判断从 i - j 是否为回文字符串
bool isPalindrome(char *s, int i, int j) 
{
	for (int k = i; k <= i + (j - i)/2; k++) {
		if (s[k] != s[j - k + i]) {
			return false;
		}
	}
	return true;
}

// 验证回文字符串Ⅱ -- 贪心算法
bool validPalindrome(char *s) 
{
	int j = strlen(s) - 1; // 计算的是真实大小
	int i = 0;

	
	while (i < j) {
		// 起始字符不相同,那只能删除头尾字符形成回文,否则就不会是回文
		if (s[i] != s[j]) {
			return (isPalindrome(s, i + 1, j) || isPalindrome(s, i, j - 1));
		}
		// 起始字符相同,继续往里面判断
		i++; // 如果s[i] == s[j], 则判断s[i+1] 和 s[j-1]
		j--;
	}

	return true;  // 如果 i >= j, 说明 s 本身就是回文字符串
}

611 有效三角形的个数

在这里插入图片描述
用了比较笨的排序方法,其实还可以使用双指针,复杂度要小些的方法。

int CmpInt(const void* a, const void* b)
{
	return *(const int*)a - *(const int*)b;
}

int triangleNumber(int *nums, int numsSize) 
{
	int count = 0;

	qsort(nums, numsSize, sizeof(int), CmpInt);

	for (int i = 0; i < numsSize - 2; i++) {
		for (int j = i + 1; j < numsSize - 1; j++) {
			for (int k = j + 1; k < numsSize; k++) {
				if (nums[i] + nums[j] > nums[k])
					count++;
			}
		}
	}

	return count;
}

344. 反转字符串

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

void swap(char *a, char *b) 
{
	char *t = NULL;
	*t = *a;
	*a = *b;
	*b = *t;
}
void reverseString(char *s, int sSize)
{
	int right = sSize - 1;
	int left  = 0;

	for (; left < right; right--, left++) {
		swap(s + left, s + right);
	}
}

.338.比特位计数

给定一个非负整数 num。对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数目并将它们作为数组返回。
在这里插入图片描述

/* 获取非负数其二进制数中的 1 的个数 */
int getNumOfOne(int num)
{
    int cnt = 0;

    while(num) {
        cnt += num & 1; // 判断 num 最右一位是否为 11 ,根据结果计数
        num = num >> 1;
    }

    return cnt;
}

在这里插入图片描述
10: 0x1010
9: 0x1001
10 & 9 == 0x1000 – 把n 最右边1变成0;

int getNumOfOne(int num)
{
    int cnt = 0;

    while(num) {
        cnt++;
        num = num & (num - 1); // 二进制数字 nn 最右边的 11 变成 00 ,其余不变
    }

    return cnt;
}

48.旋转图像

给定一个 n × n 的二维矩阵表示一个图像。
将图像顺时针旋转 90 度。
你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。
在这里插入图片描述

73. 矩阵置零

给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。

进阶:
一个直观的解决方案是使用 O(mn) 的额外空间,但这并不是一个好的解决方案。
一个简单的改进方案是使用 O(m + n) 的额外空间,但这仍然不是最好的解决方案。
你能想出一个仅使用常量空间的解决方案吗?
在这里插入图片描述
思路:
第一次遍历时,使用标记数组,记录哪行哪列出现0值
第二次遍历时,根据标记数组清0

void setZeroes(int **matrix, int matrixSize, int *matrixColSize) {
	int m = matrixSize;         // matrixSize 是该矩阵的行数
	int n = matrixColSize[0];   // matrixColSize[0] 是该矩阵的列数
	int row[m], col[n];
	memset(row, 0, sizeof(row));
	memset(col, 0, sizeof(col));
	for (int i = 0; i < m; i++) {
		for (int j = 0; j < n; j++) {
			if (!matrix[i][j]) { // 使用标记数组,记录行列值
				row[i] = 1;
				col[j] = 1;
			}
		}
	}
	for (int i = 0; i < m; i++) {
		for (int j = 0; j < n; j++) {
			if (row[i] || col[j]) {
				matrix[i][j] = 0;
			}
		}
	}
}

789. 逃脱阻碍者

在这里插入图片描述

思路:此题看上去像是一道 DFS 的题,但实际上由于ghosts也能动,所以会有点想不明白具体怎么解。
其实只需要比较 “我”和 Ghosts 各自到 target 的距离即可,如果是都是小于就可以在ghosts之前出去。
这个距离称之为曼哈顿距离。。。虽然名字有点奇怪。

在这里插入图片描述
题目中给出了target为一维有两个的数组;
ghosts为二维数组,每个也有两个;

int manhattanDistance(int *point1, int *point2)
{
	return fabs(point1[0] - point2[0]) + fabs(point1[1] - point2[1]);
}

bool escapeGhosts(int **ghosts, int ghostsSize, int *ghostsColSize, int *target, int targetSize) {
	int source[2] = { 0, 0 };
	int distance = manhattanDistance(source, target);
	for (int i = 0; i < ghostsSize; i++) {
		int ghostDistance = manhattanDistance(ghosts[i], target);
		if (ghostDistance <= distance) {
			return false;
		}
	}
	return true;
}

390. 消除游戏

列表 arr 由在范围 [1, n] 中的所有整数组成,并按严格递增排序。请你对 arr 应用下述算法:
从左到右,删除第一个数字,然后每隔一个数字删除一个,直到到达列表末尾。
重复上面的步骤,但这次是从右到左。也就是,删除最右侧的数字,然后剩下的数字每隔一个删除一个。
不断重复这两步,从左到右和从右到左交替进行,直到只剩下一个数字。
给你整数 n ,返回 arr 最后剩下的数字。
在这里插入图片描述

int lastRemaining(int n) 
{
	int head = 1;
	int cnt = n, step = 1;
	bool dir = true; // true表示正向

	while (cnt > 1) {
		// 从左边开始移除 or(从右边开始移除,数列总数为奇数)
		if (dir || cnt % 2 == 1) { // dir为false表示反向,只有反向且 cnt % 2 == 0 时不更新head
			head = head + step;
		}
		cnt  = cnt / 2;  // 步长 * 2
		step = step * 2; // 总数 / 2
		dir = !dir;      // 取反移除方向
	}

	// 每个回合更新和记录head变量,当数组的总数变为1时,head就是最后的一个数
	return head;
}

上述过程需要自己以一个实例进行推导几次,才能体会,体会后就是上述的过程。
参考:https://leetcode-cn.com/problems/elimination-game/solution/wo-hua-yi-bian-jiu-kan-dong-de-ti-jie-ni-k2uj/

1185. 一周中的第几天

在这里插入图片描述
题目有个知识应该被告知:
1970年最后一天是周四 – 已知的先验知识
题目保证日期是在 1971 到 2100 之间,我们可以计算给定日期距离 1970 的最后一天(星期四)间隔了多少天,从而得知给定日期是周几。

具体的,可以先通过循环处理计算年份在 [1971, year - 1] 时间段,经过了多少天(注意平年为 365,闰年为 366);然后再处理当前年 yearyear 的月份在 [1, month - 1] 时间段 ,经过了多少天(注意当天年是否为闰年,特殊处理 2 月份),最后计算当前月 month 经过了多少天,即再增加 day 天。
得到距离 1970 的最后一天(星期四)的天数后进行取模,即可映射回答案。

// 题目保证日期是在 1971 到 2100 之间,我们可以计算给定日期距离 1970 的最后一天(星期四)间隔了多少天,从而得知给定日期是周几
char *dayOfTheWeek(int day, int month, int year)
{
	const char *Day[7]   = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
	int  Month[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
	int  res = 4; // 1970年最后一天是周四 -- 已知的先验知识

	// 可以先通过循环处理计算年份在 [1971, year - 1] 时间段,经过了多少天(注意平年为 365,闰年为 366)
	for (int i = 1971; i < year; i++) {
		bool isLeap = (i % 4 == 0 && i % 100 != 0) || i % 400 == 0;
		res += isLeap ? 366 : 365;
	}
	// 然后再处理当前年 year 的月份在 [1,month−1] 时间段
	// 经过了多少天(注意当天年是否为闰年,特殊处理 2 月份),最后计算当前月 month 经过了多少天,即再增加 day 天。
	for (int i = 1; i < month; i++) {
		res += Month[i - 1];
		if (i == 2 && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)) {
			res++;
		}
	}
	res += day;
	res %= 7;

	return (char *)Day[res];
}

6368. 找出字符串的可整除数组

在这里插入图片描述
错误答题:
想这种题目,大概率会溢出,需要数学推演来找规律:

// 6368. 找出字符串的可整除数组
long long judge_num(long long num, long long m)
{
	long long res_s = num % m;

	return res_s == 0;
}

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int *divisibilityArray(char *word, int m, int *returnSize) 
{
	int right = 0, left = strlen(word);
	int i;
	int res = 0;
	char *tmp = (char *)malloc(sizeof(char) * strlen(word) + 1);
	int  *cnt = (int *)malloc(sizeof(int) * strlen(word) + 1);
	memset(tmp, 0, sizeof(char) * strlen(word) + 1);
	memset(cnt, 0, sizeof(int) * strlen(word) + 1);
	*returnSize = strlen(word);   
	for (i = right; i < left; i++) {
		memset(tmp, 0, sizeof(char) * strlen(word) + 1);
		memcpy((char *)tmp, (char *)word, (i + 1) * sizeof(char));
		tmp[strlen(tmp)] = '\0';
		res = judge_num(atoll(tmp), (long)m);
		if (res == 1) {
			cnt[i] = 1;
		}
	}
	
	return cnt;
}

如上为错误答案,会报:(测试用例数字太大了)
在这里插入图片描述
借鉴如下思路,每次向后增加一位时, 我们只考虑前面的余数部分, 这样是不会影响结果的。
在这里插入图片描述

int *divisibilityArray(char *word, int m, int *returnSize) 
{
	int right = 0, left = strlen(word);
	long long res = 0;
	int result ,i = 0;
	int  *cnt = (int *)malloc(sizeof(int) * strlen(word) + 1);

	memset(cnt, 0, sizeof(int) * strlen(word) + 1);
	*returnSize = strlen(word);   
	for (i = right; i < left; i++) {
		res = res * 10 + (word[i] - '0');
		result = (res % m == 0);
		if (result == 1) {
			cnt[i] = 1;
		}
		// 每次向后增加一位时, 我们只考虑前面的余数部分, 这样是不会影响结果的
		// 只保留余数部分
		res = res % m;
	}
	
	return cnt;
}

1247. 交换字符使得字符串相同

在这里插入图片描述
数学推演,找规律~
在这里插入图片描述
因此进行计数,数出s1[i],s2[i]的(‘x’, ‘y’) 和(‘y’, ‘x’) 的数量,分别计入cntxy和cntyx变量中。 按贪心思路:

(1)cntxy和cntyx均是偶数,则分别各自成对交换完成,返回:cntxy//2 + cntyx//2
(2)cntxy和cntyx均是奇数,则剩余一个(‘x’, ‘y’) 和一个(‘y’, ‘x’)需要交换两次,返回:cntxy//2 + cntyx//2 + 2
(3)cntxy和cntyx一奇一偶,则最后会剩余一个(‘x’, ‘y’) 或一个(‘y’, ‘x’)无法完成交换,返回:-1

cntxy + cntyx == 奇数一定不行,返回 -1;

int minimumSwap(char * s1, char * s2){
    short cntxy = 0, cntyx = 0;
    for (short i = 0; s1[i]; ++ i)
        if (s1[i] == 'x' && s2[i] == 'y') ++ cntxy;
        else if (s1[i] == 'y' && s2[i] == 'x') ++ cntyx;
    return (cntxy & 1) == (cntyx & 1) ? (cntxy >> 1) + (cntyx >> 1) + ((cntxy & 1) << 1) : -1;
}

面试题 05.02. 二进制数转字符串

在这里插入图片描述
在这里插入图片描述

#define MAX(a, b) ((a) > (b) ? (a) : (b))
char *printBin(double num)
{
	char *res = (char *)malloc(sizeof(int) * 33);
	int  pos  = 0;
	int  digit;
	pos  += sprintf(res, "%s", "0.");
	while (pos <= 32 && num != 0) {
		num *= 2;
		digit = num;
		res[pos++] = digit + '0';
		num -= digit;
	}
    res[pos] = '\0';
	if (pos > 32) {
		free(res);
		return "ERROR";
	}
	return res;
}
LeetCode总结 1. 数组 1.1 从有序数组中删除重复元素 1.2 在排序数组被旋转后进行查找 1.3 寻找两个排序数组的中位数 1.4 最长连续序列 1.5 累加和 1.6 移除数组中指定值 1.7 下一个排列 1.8 第n个全排列 1.9 验证数独的正确性 1.10 容纳雨水的量 1.11 旋转图像 1.12 数字加1 1.13 爬楼梯 1.14 格雷码 1.15 设置矩阵的行列为0 1.16 加油站问 1.17 分糖果 1.18 只出现一次的数 2. 单链表 2.1 单链表相加 2.2 指定位置反转单链表 2.3 依据给定值将链表重新排序 2.4 删除链表中重复元素 2.5 指定位置旋转链表 2.6 删除倒数第N个节点 2.7 成对交换链表元素 2.8 复制复杂链表 2.9 链表环相关问 2.9.1 链表是否有环 2.9.2 链表环的入口 2.10 改变链表中的元素位置2.11 LRU Cache(设计) 3. 字符串 3.1 判断字符串是否为回文 3.2 实现strStr() 3.3 字符串转为int(atoi) 3.4 二进制树相加 3.5 最长回文字符串 3.6 正则表达式匹配[hard] 3.7 正则匹配 3.8 最长公共前缀 3.9 验证字符串是否为数字 3.10 数字转为罗马数字 3.11 罗马数字到数字 3.12 Count and Say 3.13 变位词 3.14 简化系统路径 3.15 最后一个单词的长度 3.16 反转字符串中的单词 3.16.1 字符串前后和中间可能存在多个空格 3.16.2 不存在前后和中间的多余空格 3.17 一个编辑距离 4. 栈 4.1 验证括号的正确性 4.2 最长的正确括号表达式 4.3 柱状图中的最大矩形面积 4.4 计算逆波兰式的值 5. 树 5.1 二叉树的遍历 5.1.1 二叉树的前、中、后序遍历 5.1.2 二叉树的层序遍历 5.1.3 恢复二叉树[hard] 5.1.4 判断两棵树是否相等 5.1.5 判断二叉树是否为AVL树 5.1.6 将二叉树转为链表 5.1.7 二叉树添加指向右边节点的指针 5.1.8 树中节点的最小公共祖先 5.2 二叉树的构建5.3 二叉查找树 5.3.1 生成不重复的二叉查找树数目 5.3.2 验证是否为二叉查找树 5.3.3 将有序数组转为二叉树 5.3.4 将有序链表转为二叉树 5.4 二叉树的递归 5.4.1 二叉树的最大深度 5.4.2 二叉树的最小深度 5.4.3 路径和 5.4.4 满二叉树添加指向右边节点的指针 5.4.5 根节点到叶结点的所有路径代表的数字之和 6. 排序 6.1 合并两个有序数组到其中一个数组 6.2 合并两个有序链表 6.3 合并K个有序链表 6.4 使用插入排序来排序链表 6.5 归并排序排序链表 6.6 第一个缺少的正数 6.7 排序颜色 7. 查找 7.1 在排序数组中查找数出现的范围 7.2 在排序数组中查找给定值的插入位置 7.3 在二维排序数组中查找给定值 7.4 在旋转有序数组中查找最小值 7.4.1 数组无重复 7.4.2 数组有重复 7.5 在旋转排序数组中查找指定数字 8. 暴力枚举法 8.1 求集合的子集 8.2 集合的全排列 8.3 在指定树中选择进行全排列 8.4 电话上对应数字的字母组成的所有单词 9. 广度优先搜索 9.1 单词变换路径(Word Ladder) 9.1.1 是否存在变换路径 9.1.2 所有最短变换路径9.2 包围区域 10. 深度优先搜索 10.1 N皇后问 10.2 恢复IP地址 10.3 集合元素之和 10.3.1 元素可以重复 10.3.2 元素不可重复 10.3.3 给定元素数目和元素范围 10.4 正确的括号对 10.5 解数独 10.6 单词搜索 10.7 小结 10.7.1 适用场景 10.7.2 思考步骤 10.7.3 代码模板 10.7.4 深搜与回溯、递归的区别 11. 分治法 11.1 实现pow(x, n) 11.2 Sqrt(x) 12. 贪心算法 12.1 跳台阶游戏 12.2 买卖股票的最佳时机 12.2.1 最多允许交易一次 12.2.2 可以交易任意多次 12.2.3 最多可以交易两次 12.2.4 可以交易任意多次 12.2.5 交易后需要停止一段时间 12.3 最长不含重复元素的子串 12.4 存放的最大水量 13. 动态规划 13.1 三角形从顶到底的最小路径和 13.2 最大连续子数组 13.3 字符串的所有子回文字符串 13.4 最长公共子序列问 13.5 字符串的编辑距离 13.6 不同路径之和 13.6.1 无障碍13.6.2 有障碍 13.7 最大矩形面积 13.8 字符串交叉组合 13.9 旋转字符串 13.10 最小路径和 13.11 所有的编码方式 13.12 独一无二的子序列数 13.13 拆分单词 13.13.1 单词是否由词典中的单词组成 13.13.2 返回所有可以切分的解 14.14.1 图的克隆 15. 细节实现 15.1 反转整数 15.2 对称数判断 15.3 区间的相关操作 15.3.1 在区间中插入新的区间 15.3.2 合并区间 15.4 包含子串元素的最小窗口 15.5 大数乘法 15.6 给定串中是否存在包含所有单词的子串 15.7 Pascal 三角形 15.7.1 生成Pascal三角形 15.7.2 Pascal三角形的第N行 15.8 螺旋形矩阵 15.8.1 螺旋打印矩阵 15.8.2 生成螺旋矩阵 15.9 Z字形输出字符串 15.10 不使用乘、除、取模实现两个整数相除 15.11 文本对齐 15.12 共线的最大点数 16 其他问 16.1 随机数生成器
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值