1 熟能生巧
2 常见的解题思路模板要会!
1. 思路,常见的一些题目必须要会,
比如这个:
1 链表、查找、树、栈队列、 哈希
2 递归、回溯、贪心
3 字符串、双指针、模拟
其实只有: 常见的三类 !!!
2 各类题目总结:
2.1 树
1.找对最近的公共祖先:
int func(struct TreeNode* root,int o1,int o2){
int lowestCommonAncestor(struct TreeNode* root, int o1, int o2 ) {
// write code here
if(root==NULL){
return -1;
}
if( root->val==o1 ||root->val==o2){
return root->val;
}
int lres = lowestCommonAncestor(root->left, o1, o2);
int rres = lowestCommonAncestor(root->right, o1, o2);
if(lres == -1) return rres;
if(rres == -1) return lres;
return root->val;
}
}
2.树的遍历
思路:直接递归
太简单,跳过!!!
3.合并树
struct TreeNode* mergeTrees(struct TreeNode* t1, struct TreeNode* t2 ) {
// write code here
if(t1==NULL ){
return t2;
}
if(t2 == NULL){
return t1;
}
if(t1==NULL && t2==NULL){
return t1;
}
t1->val+= t2->val;
t1->left = mergeTrees(t1->left, t2->left);
t1->right = mergeTrees(t1->right,t2->right);
return t1;
}
4. 镜像树
struct TreeNode* Mirror(struct TreeNode* pRoot ) {
// write code here
if(pRoot==NULL){
return pRoot;
}
struct TreeNode* temp;
temp = pRoot->left;
pRoot->left = pRoot->right ;
pRoot->right = temp ;
Mirror(pRoot->left);
Mirror(pRoot->right);
return pRoot;
}
5 是否是二叉搜索树?
void doFunc(struct TreeNode* n, int* list, int* listSize) {
if (!n) {
return ;
}
doFunc(n->left, list, listSize);
list[(*listSize)++] = n->val;
doFunc(n->right, list, listSize);
}
bool isValidBST(struct TreeNode* root ) {
int* list = (int* )malloc(1000000*sizeof(int));
int listSize = 0 ;
doFunc(root,list,&listSize);
// int res =
for( int i=0;i<listSize-1;i++ ){
if(list[i]>list[i+1] ){
return false;
}
}
return true;
}
6 完全二叉树?
只要发现front前面这个节点是空的,如果在发现空的,那就一定有错误--
bool isCompleteTree(struct TreeNode* root ) {
// write code here
int rear=0,front=0;
struct TreeNode* list[10000];
list[rear++] = root;
while(front<rear){
struct TreeNode* cur = list[front++];
if(cur==NULL){
while(front<rear){
if(list[front]!=NULL){
return 0;
}
front++;
}
}
else{
list[rear++] = cur->left;
list[rear++] = cur->right;
}
}
return 1;
}
7 平衡二叉树?
看每个节点最大差值《=1???
1 - 找到每一个节点,返回来,在递归 2 - 在里面再来一次两次判断,看看两边的子树是不是都满足?
int getLen(struct TreeNode* root) {
if (root == NULL) {
return 0 ;
}
int lLen = getLen(root->left);
int rLen = getLen(root->right);
return (lLen>rLen?lLen:rLen)+1;
}
bool IsBalanced_Solution(struct TreeNode* pRoot ) {
// write code here
if(pRoot==NULL){
return 1;
}
int lLen = getLen(pRoot->left);
int rLen = getLen(pRoot->right);
if(abs(lLen-rLen)>1){
return 0;
}
return IsBalanced_Solution(pRoot->left)&&IsBalanced_Solution(pRoot->right);
}
8 二叉搜索树的最近的祖先节点???
直接秒杀!!!!
int lowestCommonAncestor(struct TreeNode* root, int p, int q ) {
// write code here
if(root->val==p || root->val==q){
return root->val;
}
if( (root->val<p && root->val<q) ){
return lowestCommonAncestor(root->right, p, q);
}
if( root->val>p && root->val>q ){
return lowestCommonAncestor(root->left, p, q);
}
if(( root->val<p &&root->val>q ) || (root->val<q &&root->val>p )){
return root->val;
}
else{
return -1;
}
}
9.树的最近公共祖先????
分析:对于x要么是a,要么是b,要么都是x的子树的节点!!!
思路:递归+特殊情况处理
int lowestCommonAncestor(struct TreeNode* root, int o1, int o2 ) {
// write code here
// if(root==NULL){
// return -1;
// }
// if( root->val==o1 ||root->val==o2){
// return root->val;
// }
// int lres = lowestCommonAncestor(root->left, o1, o2);
// int rres = lowestCommonAncestor(root->right, o1, o2);
// if(lres == -1) return rres;
// if(rres == -1) return lres;
// return root->val;
if(root==NULL){
return -1;
}
if(root->val==o1 || root->val==o2){
return root->val;
}
int lres = lowestCommonAncestor(root->left, o1, o2);
int rres = lowestCommonAncestor(root->right, o1, o2);
if(lres==-1) return rres;
if(rres==-1) return lres;
return root->val;
}
10.重建二叉树:从pre+in遍历重新构建一个二叉树
分析:_f_ _____pre ____ ____in_____
_____pre_____ _f_ _____in______
只要看到这个,就明白!
11.右视图
2.2 链表
3/16号全部刷完:
1.反转链表
pre/p/pNext 三大元基本法!!!不用想,直接套模板!!!
2.第一个公共节点?
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
/**
*
* @param pHead1 ListNode类
* @param pHead2 ListNode类
* @return ListNode类
*/
struct ListNode* FindFirstCommonNode(struct ListNode* pHead1,
struct ListNode* pHead2 ) {
// write code here
// struct ListNode* p = pHead1;
// struct ListNode* q = pHead2;
// if(pHead1==NULL || pHead2 ==NULL){
// return NULL;
// }
// while( p->val!=q->val ) {
// p=p->next;
// q=q->next;
// if(p==NULL && q == NULL){
// return NULL;
// }
// if(p==NULL){
// p= pHead2;
// }
// if(q==NULL){
// q = pHead1;
// }
// }
// return p;
// if (pHead1 == NULL || pHead2 == NULL) {
// return NULL;
// }
// struct ListNode* p1 = pHead1;
// struct ListNode* p2 = pHead2;
// while (p1 != p2) {
// p1 = p1->next;
// p2 = p2->next;
// if(p1==NULL&&p2==NULL){
// return NULL;
// }
// if (p1 == NULL) {
// p1 = pHead2;
// }
// if (p2 == NULL) {
// p2 = pHead1;
// }
// }
// return p1;
if (pHead1 == NULL || pHead2 == NULL) {
return NULL; // 如果任一链表为空,直接返回 NULL
}
struct ListNode* p1 = pHead1;
struct ListNode* p2 = pHead2;
// 双指针遍历
while(p1!=p2){
p1 = p1==NULL?pHead2:p1->next;
p2 = p2==NULL?pHead1:p2->next;
}
return p1; // 返回公共节点(如果没有公共节点,返回 NULL)
}
3.合并两个排序链表
太简单了,指针谁小谁做下一个,不放图了
4 两个链表相加的
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head1 ListNode类
* @param head2 ListNode类
* @return ListNode类
*/
struct ListNode* doFunc(struct ListNode* node){
struct ListNode* p=node;
struct ListNode* pre=NULL ;
struct ListNode* pNext ;
while(p!=NULL){
pNext = p->next;
p->next = pre;
pre = p ;
p = pNext;
}
return pre;
}
struct ListNode* addInList(struct ListNode* head1, struct ListNode* head2 ) {
// write code here
struct ListNode* a = doFunc(head1);
struct ListNode* b = doFunc(head2);
struct ListNode* s = NULL;
struct ListNode* head= s;
int jin = 0 ;
while(a!=NULL || b!=NULL || jin!=0){
struct ListNode* newNode = (struct ListNode*)malloc(sizeof(struct ListNode));
int val1 = (a==NULL)?0:a->val;
int val2 = (b==NULL)?0:b->val;
newNode->val = val1 + val2+ jin;
newNode->next = NULL;
jin=0;
if(newNode->val >=10){
jin=1;
newNode->val = newNode->val-10;
}
if(s==NULL){
s = newNode;
head =s ;
}
else{
s->next = newNode;
s = s->next;
}
a= (a==NULL)?NULL:a->next;
b= (b==NULL)?NULL:b->next;
}
return doFunc(head);
}
做了整整两个小时,最后的条件判断很重要
5.链表中是否有环?
2.快慢指针,总会追上!!!
bool hasCycle(struct ListNode* head ) {
// write code here
struct ListNode* fast = head;
struct ListNode* slow = head;
if (head == NULL || head->next == NULL) {
return false;
}
// while (fast!= NULL && fast->next != NULL) {
// fast = fast->next->next;
// slow = slow->next;
// if (fast == slow) {
// return true;
// }
// }
//重新写一遍
while(fast!=NULL && fast ->next!=NULL){
fast=fast->next->next;
slow=slow->next;
if(fast==slow){
return true;
}
}
return false;
}
6 第一个环开始的地方?
思维:
1 就是重复出现的第一个地方,只要val取负数就可以!
struct ListNode* EntryNodeOfLoop(struct ListNode* pHead ) {
// write code here
struct ListNode* p = pHead;
// while(fast->next!= NULL && fast!=NULL){
// fast = fast->next->next;
// slow = slow->next;
// if(fast==slow){
// return fast;
// }
// }
while(p!=NULL && p->next !=NULL){
// if(p->val>0){
// p->val = 0-p->val;
// p = p->next;
// }
// else{
// p->val = 0-p->val;
// return p;
// }
if(p->val>0){
p->val = 0-p->val;
p=p->next;
}
else{
p->val = 0-p->val;
return p;
}
}
return NULL;
}
7.倒数第k哥节点?
太简单了,
1 2 3 4 5 6 7 8 9 10
倒数第3个节点就是8,查了2个数,
8.两个链表的第一个公共节点?
太简单了,交叉往后走即可!!!
9.链表相加?复杂!!!
a:1 3 7
b:2 9 6
=
1 4 3 3
先倒过来,再分别加,利用flag记住进位,再return倒过来的现在的p节点!!!
10 归并排序? 复杂!!!
merge先分后治!!!
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head ListNode类 the head node
* @return ListNode类
*/
struct ListNode* mid(struct ListNode* head) {
struct ListNode* newHead = malloc(sizeof(struct ListNode));
newHead->next = head;
struct ListNode* slow = newHead ;
struct ListNode* fast = newHead;
while (fast != NULL && fast->next != NULL) {
slow = slow->next;
fast = fast->next->next;
}
struct ListNode* res = slow->next ;
slow->next = NULL;
return res;
}
struct ListNode* merge(struct ListNode* a, struct ListNode* b ) {
struct ListNode* H = (struct ListNode* )malloc(sizeof(struct ListNode));
struct ListNode* p = H;
while (a != NULL && b != NULL) {
if (a->val < b->val) {
p->next = a;
a = a->next;
} else {
p->next = b;
b = b->next;
}
p = p->next ;
}
if (a == NULL) {
p->next = b;
}
if (b == NULL) {
p->next = a ;
}
return H->next;
}
struct ListNode* sortInList(struct ListNode* head ) {
// write code here
//第一步:先给他拆分,各自排序,然后merge直接合并起来
//第二步:时限拆分mid,合并两个算法
//完成主函数
if ( head == NULL || head->next == NULL) {
return head;
}
struct ListNode* leftNode = head;
struct ListNode* rightNode = mid(head);
leftNode = sortInList(leftNode);
rightNode = sortInList(rightNode);
return merge(leftNode, rightNode);
}
11.回文字符串
简单!!!
12.奇数偶数重排??
技巧!!!
struct ListNode* oddEvenList(struct ListNode* head ) {
// write code here
struct ListNode* p1 = head;
struct ListNode* p2 = head->next;
struct ListNode* p3= p2;
if(head ==NULL){
return head;
}
// struct ListNode* p2 = (struct ListNode*)malloc(sizeof(struct ListNode));
while(p2!=NULL && p2->next!=NULL){
p1->next = p2->next;
p1 = p1->next;
p2->next = p1->next;
p2 =p2->next;
}
p1->next = p3;
return head;
}
12.删掉重复的元素?
简单!!!直接往后面跳着就行了
struct ListNode* p = head;
struct ListNode* newHead = malloc(sizeof(struct ListNode));
newHead ->next = head;
int temp = 0;
while (p != NULL) {
temp = p ->val;
while (p->next != NULL && p->next->val == temp) {
p->next = p->next->next;
}
p = p->next;
}
return newHead->next;
13.删掉所有重复的元素??? 复杂
if(head ==NULL || head ->next==NULL){
return head;
}
struct ListNode* newHead = (struct ListNode* )malloc(sizeof(struct ListNode));
newHead ->next = head;
struct ListNode* p = newHead;
while(p->next !=NULL && p->next->next!=NULL){
if( p->next->val==p->next->next->val ){
int temp = p ->next->val;
while(temp == p->next->val && p->next!=NULL){
p->next = p->next->next;
}
}
else{
p = p->next;
}
}
return newHead->next;
2.3 排序算法/二分查找
1.二分查找?简单,吃饭喝水一样。。。。
智商题!!!!!
2.找到波峰元素?
如果mid>mid+1,那么峰在左侧或者mid本身,
else,峰值一定不是她自己!!!
int findPeakElement(int* nums, int numsLen ) {
// write code here
int left = 0 ;
int right = numsLen-1;
while(left<right){
int mid = (left+right)/2;
if(nums[mid]>nums[mid+1]){
right= mid;
}
else{
left = mid+1;
}
}
return right;
}
还有一种方法:
从1到len-1遍历整个数组,如果比两边大,直接返回,然后对0 和len位置,分别考虑即可。。。枝智商题!
3.数组的逆序对?
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型一维数组
* @param numsLen int nums数组长度
* @return int整型
*/
long long merge(int* nums,int* temp ,int left ,int mid,int right){
//先ikj左右分别处理
int i = left,j=mid+1,k=left;
long long cnt = 0;
while(i<=mid&& j<=right){
if(nums[i]<=nums[j]){
temp[k++] = nums[i++];
}
else{
temp[k++] = nums[j++];
cnt += (mid-i+1);
}
}
while(i<=mid){
temp[k++] = nums[i++];
}
while(j<=right){
temp[k++] = nums[j++];
}
//再把剩下的元素补充道temp
for(int i = left ;i<=right;i++){
nums[i]=temp[i];
}
// 最后再把temp的放到nums里面去
return cnt;
}
long long merge_sort(int* nums,int* temp ,int left,int right ){
long long cnt = 0;
if(left<right){
int mid = (left+right)/2;
cnt += merge_sort(nums, temp, left, mid);
cnt += merge_sort(nums, temp, mid+1, right);
cnt += merge(nums,temp,left,mid,right);
}
return cnt ;
}
int InversePairs(int* nums, int numsLen ) {
// write code here
long long cnt =0;
int* temp = (int*)malloc(numsLen*sizeof(int));
cnt = (long long)merge_sort(nums,temp ,0,numsLen-1 );
return cnt % 1000000007;
}
有难度,有四位模板!!!
归并排序思维
4 旋转数组的最小数字
二分查找!!!
int minNumberInRotateArray(int* nums, int numsLen ) {
// write code here
int left =0 ,right =numsLen-1;
while(left<right){
int mid = (left+right)/2;
if(nums[mid]>nums[right]){
left =mid+1;
}
else if(nums[mid]<nums[right]){
right =mid;
}
else{
right--;
}
}
return nums[right];
}
2.4 栈/队列
1有效序列括號?
()[]{}這種情況下,哪些是有效的括號?
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param s string字符串
* @return bool布尔型
**/
bool isValid(char* s ) {
// write code here
// char stack[1000];
char* stack = (char* )malloc(10000*sizeof(char));
int top = -1;
int len = strlen(s);
if(len%2!=0){
return false;
}
if(len==0){
return true;
}
for(int i = 0 ;i<len;i++){
if(s[i]=='(' || s[i]=='{'|| s[i]=='['){
stack[++top] = s[i];
}
else {
if(top==-1){
return false;
}
char x = stack[top--];
if( ( s[i]==')'&& x!='(' ) || (s[i]=='}'&&x!='{' )
||( s[i]==']'&&x!='[') )
{
return false;
}
}
}
return top==-1;
}
2 包含min的栈?
c语言直接用两个stack,一个普通的,一个min_stack
进去时候,判断一下min_stack是不是最小的?
static int stack[300],min_stack[300];
static int s_top = 0 ,m_top = 0;
void push(int value ) {
// write code here
if(m_top == 0 ){
min_stack[m_top++] = value;
}
else{
if(value<=min_stack[m_top-1]){
min_stack[m_top++]= value;
}
}
stack[s_top++]= value;
}
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param 无
* @return 无
*/
void pop() {
// write code here
if(stack[s_top-1]==min_stack[m_top-1]){
m_top--;
}
s_top--;
}
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param 无
* @return int整型
*/
int top() {
// write code here
return stack[s_top-1];
}
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param 无
* @return int整型
*/
int min() {
// write code here
return min_stack[m_top-1];
}
3 有效括号序列?
直接strlen求出s的长度
1 如果奇数 ,直接不用算了
2 如果是:( { [ 压进去再说
3.1 如果不是,top==-1 直接失败
3.2 如果栈顶如果不匹配 x = stack[top--]
s[i]=='(' x!=')'
失败!
4 return top ==-1?
4最小的k个数字?
直接冒泡排序
void bubbleSort(int *arr, int length)
{ // 采用最简单的冒泡排序
//两次循环
for(int i = 0 ;i<length-1;i++){
for(int j =0;j<length-i-1;j++){
if(arr[j]>arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] =temp;
}
}
}
}
int *GetLeastNumbers_Solution(int *input, int inputLen, int k, int *returnSize)
{
// write code here
if(k<0 || k>inputLen || input==NULL){
return NULL;
}
int *res = (int *)malloc(10000 * sizeof(int));
// 直接用BubbleSort排序,把指针传进去
bubbleSort(input, inputLen);
for(int i = 0 ;i<k;i++){
res[i]=input[i];
}
*returnSize = k ;
return res;
}
5.第k大的数?快排法!
-1:{
j=left,i=left-1
for(int j =left;j<right)
如果j>i
i++
swap(j, i的元素)
}
0: doFunc1(a, left ,right,k){
如果这一轮的数字正好为k
if(left==right) return left;
pivot = partition(left,right)
否则:
a:partition(a, left,pivot-1)
b:partition(a,pivot+1,right)
}
1:主函数
正常作为接口
6数据的中位数?
7
2.5 哈希法
1.出现次数超过一半的数字?
直接根据hash数组找到里面那些Hash[i]超过1/2Length ,找到了直接返回那个值
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param numbers int整型一维数组
* @param numbersLen int numbers数组长度
* @return int整型
*/
int MoreThanHalfNum_Solution(int* numbers, int numbersLen ) {
// write code here
int hash[100000] = {0};
for(int i= 0 ;i<numbersLen;i++){
hash[numbers[i]]++;
}
for(int i= 0;i<100000;i++){
if(hash[i]>numbersLen/2){
return i;
}
}
// return i;
return 1;
}
2.数组中只出现一次的两个数字:
搞一个hash表就行了
#define MAX_size 1000001
int* FindNumsAppearOnce(int* nums, int numsLen, int* returnSize ) {
int hash[MAX_size] = {0};
// for (int i = 0 ; i < MAX_size; i++) {
// printf("%d\n,", hash[i]);
// }
for (int i = 0 ; i < numsLen; i++) {
hash[nums[i]]++;
}
int* res = (int*)malloc(2*sizeof(int));
int cnt = 0;
*returnSize =2;
for (int i = 0; i < numsLen; i++) {
if (hash[nums[i]] == 1) {
res[cnt++] = nums[i];
if (cnt == 2) {
break;
}
}
}
if (res[0] > res[1]) {
int t = res[0];
res[0] = res[1];
res[1] = t ;
}
return res;
}
3.缺失的第一个最小的正整数? [1,2,3,4] -> 5 [1,-1,3]->2
直接用辅助的存一下出现过的!
int minNumberDisappeared(int* nums, int numsLen ) {
// write code here
int* arr = (int*)malloc(100000 * sizeof(int));
int i = 0;
for ( i = 0 ; i < numsLen; i++) {
arr[i] = 0;
}
for ( i = 0 ; i < numsLen; i++) {
if (nums[i] > 0 && nums[i] <=numsLen) {
arr[nums[i]-1] = 1;
}
}
for (i=0; i < numsLen; i++) {
if (arr[i] == 0) {
break;
}
}
return i + 1;
}
2. 6 递归/回溯
1.有重复的数字序列全排列?
这个题目初看上去很复杂,确实做的时候也比较麻烦,初学者看到直接蒙蔽了,绕来绕去;
本人写这个题目的时候用了将近2哥小时才看明白1,2,3这个序列简单过程的排序方法和过程:
循环的两次过程:
整个运行过程:
运行过程
初始调用
在 permute 函数中,会调用 backtrack(num, 0, numLen - 1, &result, returnSize),这里 num = [1, 2, 3],start = 0,end = 2,result 是用于存储所有排列的二维数组,count 初始值为 0。
第一次调用 backtrack
参数:nums = [1, 2, 3],start = 0,end = 2。
判断条件:start 不等于 end,进入 else 分支。
循环过程:
i = 0 时:
交换元素:调用 swap(&nums[0], &nums[0]),数组不变,仍为 [1, 2, 3]。
递归调用:调用 backtrack(nums, 1, 2, result, count)。
第二次调用 backtrack
参数:nums = [1, 2, 3],start = 1,end = 2。
判断条件:start 不等于 end,进入 else 分支。
循环过程:
i = 1 时:
交换元素:调用 swap(&nums[1], &nums[1]),数组不变,还是 [1, 2, 3]。
递归调用:调用 backtrack(nums, 2, 2, result, count)。
第三次调用 backtrack
参数:nums = [1, 2, 3],start = 2,end = 2。
判断条件:start 等于 end,进入 if 分支。
操作过程:
分配内存:(*result)[*count] = (int *)malloc((end + 1) * sizeof(int)); 为当前排列分配内存。
复制排列:通过 for 循环将 nums 数组的元素复制到 (*result)[*count] 中,也就是把 [1, 2, 3] 存到 result 里。
增加计数:(*count)++,此时 count 变为 1。
回到第二次调用的 backtrack
回溯操作:调用 swap(&nums[1], &nums[1]),数组仍为 [1, 2, 3]。
循环继续:
i = 2 时:
交换元素:调用 swap(&nums[1], &nums[2]),数组变为 [1, 3, 2]。
递归调用:调用 backtrack(nums, 2, 2, result, count)。
第四次调用 backtrack
参数:nums = [1, 3, 2],start = 2,end = 2。
判断条件:start 等于 end,进入 if 分支。
操作过程:
分配内存:为当前排列分配内存。
复制排列:把 [1, 3, 2] 存到 result 中。
增加计数:(*count)++,此时 count 变为 2。
回到第二次调用的 backtrack
回溯操作:调用 swap(&nums[1], &nums[2]),数组变回 [1, 2, 3]。
回到第一次调用的 backtrack
回溯操作:调用 swap(&nums[0], &nums[0]),数组仍为 [1, 2, 3]。
循环继续:
i = 1 时:
交换元素:调用 swap(&nums[0], &nums[1]),数组变为 [2, 1, 3]。
递归调用:调用 backtrack(nums, 1, 2, result, count)。
参数:nums = [2, 1, 3],start = 1,end = 2。
判断条件:start 不等于 end,进入 else 分支。
循环过程:
i = 1 时:
交换元素:调用 swap(&nums[1], &nums[1]),数组不变,为 [2, 1, 3]。
递归调用:调用 backtrack(nums, 2, 2, result, count)。
参数:nums = [2, 1, 3],start = 2,end = 2。
判断条件:start 等于 end,进入 if 分支。
操作过程:
分配内存:为当前排列分配内存。
复制排列:把 [2, 1, 3] 存到 result 中。
增加计数:(*count)++,此时 count 变为 3。
i = 2 时:
交换元素:调用 swap(&nums[1], &nums[2]),数组变为 [2, 3, 1]。
递归调用:调用 backtrack(nums, 2, 2, result, count)。
参数:nums = [2, 3, 1],start = 2,end = 2。
判断条件:start 等于 end,进入 if 分支。
操作过程:
分配内存:为当前排列分配内存。
复制排列:把 [2, 3, 1] 存到 result 中。
增加计数:(*count)++,此时 count 变为 4。
回溯操作:调用 swap(&nums[1], &nums[2]),数组变回 [2, 1, 3]。
回到第一次调用 backtrack 里的此次递归调用处:
回溯操作:调用 swap(&nums[0], &nums[1]),数组变回 [1, 2, 3]。
i = 2 时:
交换元素:调用 swap(&nums[0], &nums[2]),数组变为 [3, 2, 1]。
递归调用:调用 backtrack(nums, 1, 2, result, count)。
参数:nums = [3, 2, 1],start = 1,end = 2。
判断条件:start 不等于 end,进入 else 分支。
循环过程:
i = 1 时:
交换元素:调用 swap(&nums[1], &nums[1]),数组不变,为 [3, 2, 1]。
递归调用:调用 backtrack(nums, 2, 2, result, count)。
参数:nums = [3, 2, 1],start = 2,end = 2。
判断条件:start 等于 end,进入 if 分支。
操作过程:
分配内存:为当前排列分配内存。
复制排列:把 [3, 2, 1] 存到 result 中。
增加计数:(*count)++,此时 count 变为 5。
i = 2 时:
交换元素:调用 swap(&nums[1], &nums[2]),数组变为 [3, 1, 2]。
递归调用:调用 backtrack(nums, 2, 2, result, count)。
参数:nums = [3, 1, 2],start = 2,end = 2。
判断条件:start 等于 end,进入 if 分支。
操作过程:
分配内存:为当前排列分配内存。
复制排列:把 [3, 1, 2] 存到 result 中。
增加计数:(*count)++,此时 count 变为 6。
回溯操作:调用 swap(&nums[1], &nums[2]),数组变回 [3, 2, 1]。
回到第一次调用 backtrack 里的此次递归调用处:
回溯操作:调用 swap(&nums[0], &nums[2]),数组变回 [1, 2, 3]。
最终结果
经过上述一系列的递归调用和回溯操作,result 数组中存储了 [1, 2, 3]、[1, 3, 2]、[2, 1, 3]、[2, 3, 1]、[3, 2, 1]、[3, 1, 2] 这 6 个排列,count 的值变为 6,表示已经生成了 6 种不同的排列。