彻底吃透大厂面试编程题 之 牛客高频必刷题目解题思路详解+c语言贪吃蛇坦克大战超级经典编程问题大全解!所有接替分析+总结

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数据的中位数?

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 种不同的排列。

2.无重复的数字序列全排列?

2.7 动态规划

2.8 字符串

2.9 双指针

2.10   贪心


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值