大一考核题解

news2024/10/1 7:46:03

在本篇中,将尽力使用多种解法,来达到一题多练的效果。



1:

1.原题链接:

238. 除自身以外数组的乘积 - 力扣(LeetCode)

image-20240416152300057


这道题首先一眼肯定想到拿整体的积除以当前元素,将结果作为ans,但是一来题目说了不要用除法,二来除法要注意零元素。(虽然实际上是可以用除法来写的)


前缀:

所以我们就要换思路来写,要除了当前元素外的所有元素的积,也就是前面元素的积乘后面元素的积,这里就能想到前缀和后缀两点,所以首先可以先找出来每个元素之前的元素的积,存入一个数组,之后再找出该元素后面的元素的乘积,与前缀相乘即可。

所以这里我们就先动态分配一个数组

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* productExceptSelf(int* nums, int numsSize, int* returnSize){
    int i=0, pro = 1;
    int *ans = malloc(numsSize * sizeof(int));

    for (i = 0; i < numsSize; i++) {
        ans[i] = pro;
        pro = pro * nums[i];
    }

    pro = 1;
    for (i = numsSize - 1; i >=0 ; i--) {
        ans[i] = ans[i] * pro;
        pro = nums[i]*pro;
    }
    
    *returnSize = numsSize;
    return res;
}

这里的pro是中间变量,我们将这个中间变量不断与当前元素相乘,就得到了前缀。

注意:

这里先将pro赋值给ans是因为要求的是:要除去当前元素的前缀和。所以先赋值之后再进行操作。

接下来,pro置为1,倒着遍历数组求出后缀并于ans相乘就可以得到答案。



下面是取巧的做法,

使用除法,先遍历一遍找出所有0,将非0项求积。

再遍历分四种情况:

1.0的个数大于1,那么剩下肯定是0

2.0个数为1,判断当前元素是否为0,是0,则就是上面所求的积,反之则是0

3.没有0,那么直接就是计算出的积除以当前元素。

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* productExceptSelf(int* nums, int numsSize, int* returnSize) {
    int* ans = (int*)malloc(sizeof(int) * numsSize);
    memset(ans,1,sizeof(int)*numsSize);
    long long sum = 1;
    long long zero = 0;
    for (int i = 0; i < numsSize; i++) {
        if (nums[i] != 0)
            sum *= nums[i];
        else
            zero++;
    }
    for (int i = 0; i < numsSize; i++) {
        if (zero > 1) {
            ans[i] = 0;
        } else if (zero == 1 && nums[i] == 0) {
            ans[i] = sum;
        } else if (zero == 1 && nums[i] != 0) {
            ans[i] = 0;
        } else if (zero == 0) {
            ans[i] = sum / nums[i];
        }
    }
    *returnSize = numsSize;
    return ans;
}



2:

2.原题链接:

394. 字符串解码 - 力扣(LeetCode)

image-20240416161215575

本题难点在于括号内嵌套括号,需要从内向外生成与拼接字符串,这与栈的先入后出特性对应。


我的思路是,创建一个栈保存字符,创建一个数组保存数字。

遇到左括号,则索引位置入栈(输出串的尾指针);

遇到“ ] ”时,从索引栈里弹出栈顶元素——就是最近的与之闭合的左括号,这部分内容是要被复制的,再找到数字数组最新元素元素,是几就把这部分内容复制几遍。

然后塞回栈中,等待之后使用。

这里的难点在于:要处理的太多了,很容易脑子就乱了,稍微简化一点的话,可以将数字数组删除,直接数字入栈,找到‘[’,他前面就是数字,这个时候,直接取出这个数字就可以了

char* decodeString(char* s) {
    int len = (int)strlen(s);
    int stackSize = 50;
    char* stack = (char*)malloc(stackSize * sizeof(char));
    int top = -1;

    for (int i = 0; i < len; i++) {
        char c = s[i];
        if (c != ']') {
            if (top == stackSize - 1) {
                stack = realloc(stack, (stackSize += 50) * sizeof(char));
            }
            stack[++top] = c;
        } else {

            int tempSize = 10;
            char* tempStack = (char*)malloc(tempSize * sizeof(char));
            int tempTop = -1;
            while (stack[top] != '[') {
                if (tempTop == tempSize - 1) {
                    tempStack =
                        realloc(tempStack, (tempSize += 10) * sizeof(char));
                }
                tempStack[++tempTop] = stack[top];
                top--;
            }

            char* cpyStr = (char*)malloc((tempTop + 2) * sizeof(char));
            for (int i = tempTop; i >= 0; i--) {
                cpyStr[tempTop - i] = tempStack[i];
            }
            cpyStr[++tempTop] = '\0';

            top--;

            int cpyNum = 0;
            int j = 0;
            while (top >= 0 && stack[top] >= '0' && stack[top] <= '9') {
                cpyNum += (stack[top] - '0') * pow(10, j);
                top--;
                j++;
            }

            for (int i = 0; i < cpyNum; i++) {
                for (int j = 0; j < strlen(cpyStr); j++) {
                    if (top == stackSize - 1) {
                        stack =
                            realloc(stack, (stackSize += 50) * sizeof(char));
                    }
                    stack[++top] = cpyStr[j];
                }
            }

            free(tempStack);
        }
    }

    char* result = realloc(stack, (top + 2) * sizeof(char));
    result[++top] = '\0';

    return result;
}



3:

3.原题链接:

73. 矩阵置零 - 力扣(LeetCode)

image-20240419175111642

如果遍历一遍该数组边遍历边置零的话,就会导致之前置零的影响之后的。

所以我们先遍历一遍,将每一个地方是0的元素都标记为1,之后再遍历hash数组,将原来为1的地方进行操作变成0就行了。

这里的
image-20240419175346717

O(mn)的额外空间就是二维hash数组

O(m+n)就是用两个数组

一旦元素为0,就将该位置的下标地方的a,b数组都置为1,

这样遍历的时候只要两个同时为1就可以保证这个元素要改。

void setZeroes(int** matrix, int matrixSize, int* matrixColSize) {
    int h = matrixColSize[0];
    int l = matrixSize;
    int a[l][h];
    

    for (int i = 0; i < l; i++) {
        for (int j = 0; j < h; j++) {
            if (matrix[i][j] == 0) {
                a[i][j] = 1;
            } else {
                a[i][j] = 0;
            }
        }
    }
    

    for (int i = 0; i < l; i++) {
        for (int j = 0; j < h; j++) {
            if (a[i][j] == 1) {
                for (int k = 0; k < l; k++) {
                    matrix[k][j] = 0;
                }
                for (int k = 0; k < h; k++) {
                    matrix[i][k] = 0;
                }
            }
        }
    }
}



4:

4.原题链接:

23. 合并 K 个升序链表 - 力扣(LeetCode)

image-20240419180147978


这是合并两个升序链表这道题的plus版,合并两个的时候,我们怎么处理呢?


用归并排序的思路来:


递归:

如果 l1 或者 l2 一开始就是空链表 ,那么没有任何操作需要合并,所以我们只需要返回非空链表。>否则,我们要判断 l1 和 l2 哪一个链表的头节点的值更小,然后递归地决定下一个添加到结果里的>节点。如果两个链表有一个为空,递归结束。


迭代:

1.初始化: 伪头节点 dum ,节点 cur 指向 dum 。
2.循环合并:当或2为空时跳出。
a.当 l.val < lz.val 时: cur 的后继节点指定为,并向前走一步
b.当 l.val > z.val 时:
cur 的后继节点指定为 2,并2 向前走 步
c.节点 cur 向前走一步,即 cur = cur.next 。
3.合并剩余尾部: 跳出时有两种情况,即,为空或2为空
a.若 l 头null : 将 添加至节点 cur 之后
b.否则: 将1。添加至节点 cur 之后
4.返回值:合并链表在伪头节点 dum 之后,因此返回 dum.neat 即可。

那么放大到n个的时候我们完全可以一个一个来,每一次都将list[i]与list[0]链接,那么之后呢链接的新链表又是list[0],再与之后的链接,我们就可以用同样的思路完成该题。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    if(list1 == NULL){
        return list2;
    }
    if(list2 == NULL){
        return list1;
    }
    struct ListNode* ans;
    if(list1->val <= list2->val){
        ans = list1;
        ans->next = mergeTwoLists(list1->next,list2);
    }
    else{
        ans = list2;
        ans->next = mergeTwoLists(list1,list2->next);
    }
    return ans;

}

struct ListNode* mergeKLists(struct ListNode** lists, int listsSize) {
    if(!listsSize) return NULL;
    struct ListNode* head = NULL;
    for(int i = 0; i < listsSize; i++){
        head = mergeTwoLists(head,lists[i]);
    }
    return head;
}



取巧法:

接下来,是另一个思路,说是升序链表,又没说必须操作链表,那我们就将所有元素取出存入数组,排序之后,再存入一个新链表不就可以了吗。逃课代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
int cmp(const void* a, const void* b) { return *(int*)a - *(int*)b; }
struct ListNode* mergeKLists(struct ListNode** lists, int listsSize) {
    int a[10000];
    int j = 0;
    for (int i = 0; i < listsSize; i++) {
        struct ListNode* move = lists[i];
        while (move) {
            a[j++] = move->val;
            move = move->next;
        }
    }
    qsort(a, j, sizeof(int), cmp);
    struct ListNode* q = (struct ListNode*)malloc(sizeof(struct ListNode));
    q->next = NULL;
    struct ListNode* dong = q;
    for (int i = 0; i < j ; i++) {
        struct ListNode* new =
            (struct ListNode*)malloc(sizeof(struct ListNode));
        new->val = a[i];
        new->next = NULL;
        dong->next = new;
        dong = dong->next;
    }
    return q->next;
}



5:

5.原题链接:

232. 用栈实现队列 - 力扣(LeetCode)

image-20240421180228656

学队列的时候必练的题目:

我们用两个栈模拟一个队列,入队操作的时候进入in,出队时,先将in的出栈到out中,再从out出栈就可以完成出队操作。


typedef struct a {
    int stcin[10], stcout[10];
    int stcintop, stcouttop;
} MyQueue;

MyQueue* myQueueCreate() {
    MyQueue* q = (MyQueue*)malloc(sizeof(MyQueue));
    q->stcintop = 0;
    q->stcouttop = 0;
    return q;
}

void myQueuePush(MyQueue* obj, int x) { obj->stcin[obj->stcintop++] = x; }

int myQueuePop(MyQueue* obj) {
    if (obj->stcouttop == 0) {
        while (obj->stcintop > 0) {
            obj->stcout[obj->stcouttop++] = obj->stcin[--obj->stcintop];
        }
    }
    int ans = obj->stcout[--obj->stcouttop];
    while (obj->stcouttop > 0) {
        obj->stcin[obj->stcintop++] = obj->stcout[--obj->stcouttop];
    }
    return ans;
}

int myQueuePeek(MyQueue* obj) { 
    return obj->stcin[0]; }

bool myQueueEmpty(MyQueue* obj) {
    return obj->stcintop == 0 && obj->stcouttop == 0;
}

void myQueueFree(MyQueue* obj) {
    obj->stcintop = 0;
    obj->stcouttop = 0;
}

/**
 * Your MyQueue struct will be instantiated and called as such:
 * MyQueue* obj = myQueueCreate();
 * myQueuePush(obj, x);

 * int param_2 = myQueuePop(obj);

 * int param_3 = myQueuePeek(obj);

 * bool param_4 = myQueueEmpty(obj);

 * myQueueFree(obj);
*/



6:

6.原题链接:

61. 旋转链表 - 力扣(LeetCode)

image-20240421180541286


首先是常规的模拟法

假设链表的长度为n,为了将链表每个节点向右移动 k 个位置,我们只需要将链表的后 k % n个节点移动到链表的最前面,然后将链表的后k % n个节点和前 n - k个节点连接到一块即可。

具体过程如下:

1、首先遍历整个链表,求出链表的长度n,并找出链表的尾节点tail。

2、由于k可能很大,所以我们令 k = k % n,然后再次从头节点head开始遍历,找到第n - k个节点p,那么1 ~ p是链表的前 n - k个节点,p+1 ~ n是链表的后k个节点。

3、接下来就是依次执行 tail->next = head,head = p->next,p->next = nullptr,将链表的后k个节点和前 n - k个节点拼接到一块,并让head指向新的头节点(p->next),新的尾节点即p节点的next指针指向null。

4、最后返回链表的新的头节点head。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

struct ListNode* rotateRight(struct ListNode* head, int k) {
    if (!head || !k) return head;
    
    int n = 0; // 链表的长度
    struct ListNode* tail; // 尾节点
    
    struct ListNode* p = head;
    while (p) {
        tail = p;
        p = p->next;
        n++;
    }
    
    k %= n;
    
    p = head;
    for (int i = 0; i < n - k - 1; i++) p = p->next; // 找到链表的第n-k个节点
    
    tail->next = head;
    head = p->next;
    p->next = NULL;
    
    return head; // 返回新的头节点
}




接下来是取巧法:

我们看到这种,那继续之前合并k个链表的思路,只管开头和结尾,将元素取出组成数组,然后将整个数组复制一份接到另一个数组之后,接下来,只需要将第一个元素更新为k%n个,那就是将链表移动k个之后的链表的样子啦,我们再将数值赋值进新链表就可以完美解决。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* rotateRight(struct ListNode* head, int k) {
    if (head == NULL || head->next == NULL)
        return head;
    if (k == 0)
        return head;
    int a[501];

    int j = 0;

    struct ListNode* move = head;
    while (move) {
        a[j++] = move->val;
        move = move->next;
    }
    int b[j * 2];
    for (int i = 0; i < j; i++) {
        b[i + j] = a[i];
        b[i] = a[i];
    }
    for (int i = 0; i < j; i++) {
        printf("%d", a[i]);
    }
    struct ListNode* q = (struct ListNode*)malloc(sizeof(struct ListNode));
    q->next = NULL;
    struct ListNode* dong = q;
    for (int i = (j - k % j); i < j+(j - k % j) ; i++) {
        struct ListNode* new =
            (struct ListNode*)malloc(sizeof(struct ListNode));
        new->val = b[i];
        new->next = NULL;
        dong->next = new;
        dong = dong->next;
    }

    return q->next;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1614013.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

护眼台灯哪个牌子最好?盘点五款目前比较好用的护眼台灯

护眼台灯哪个牌子好&#xff1f;护眼台灯比较好的牌子有书客、雷士、爱德华医生等。这些护眼台灯得益于强大的研发实力&#xff0c;不仅具备基础的照明功能&#xff0c;更在护眼效果上表现卓越。它们能够真正起到保护眼睛的作用&#xff0c;有效缓解眼部疲劳&#xff0c;为阅读…

Unity3D 羊了个羊等游戏工程源码/3D资源 大合集

Unity3D休闲益智游戏工程源码大合集 一、关卡类游戏工程源码二、跑酷类游戏工程源码三、消除合成类游戏工程源码四、棋牌类游戏工程源码五、RPG(角色扮演)类游戏工程源码六、FPS&#xff08;射击&#xff09;类游戏工程源码十、Unity3D工艺仿真六、Unity游戏资源1、Unity3D 吃鸡…

怎样快速打造二级分销小程序

乔拓云是一个专门开发小程序模板的平台&#xff0c;致力于帮助商家快速上线自己的小程序。通过套用乔拓云提供的精美模板&#xff0c;商家无需具备专业的技术背景&#xff0c;也能轻松打造出功能齐全、美观大方的小程序。 在乔拓云的官网&#xff0c;商家可以免费注册账号并登录…

【批量区域识别内容重命名】批量识别图片区域文字并重命名,批量图片部分识别内容重命文件,PDF区域识别提取重命名

我们在工作和生活中经常遇到这样的需求&#xff1a;比如将以下的图片区域识别进行重命名&#xff0c;批量识别后改成以时间和工作内容重命名&#xff0c;便于日后检索&#xff0c;快速查询 首先我们拍摄照片用到的是水印相机&#xff0c;这里的文字呢我们需要加个背景&#xff…

[数字人]唇形驱动,不生成头部动作算法总结

安全验证 - 知乎知乎&#xff0c;中文互联网高质量的问答社区和创作者聚集的原创内容平台&#xff0c;于 2011 年 1 月正式上线&#xff0c;以「让人们更好的分享知识、经验和见解&#xff0c;找到自己的解答」为品牌使命。知乎凭借认真、专业、友善的社区氛围、独特的产品机制…

【数据结构】时间复杂度的例题

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;数据结构 &#x1f337;追光的人&#xff0c;终会万丈光芒 前言&#xff1a; 这篇文章是关于时间复杂度的一些例题&#xff0c;关于时间复杂度和空间复杂度和算法的计算效率的基本知识点我放在…

【题解】NC1 大数加法(高精度加法)

https://editor.csdn.net/md?not_checkout1&spm1015.2103.3001.8066&articleId138048516 class Solution { public:string solve(string s, string t) {// write code herestring ret;int tmp 0; // 进位 本次累加和int i s.size()-1, j t.size()-1;while (i &g…

Token 在 LLM

大语言模型不能理解原始文本,所以需要把原始文本转换成大语言模型可以理解的数字表示形式,经过大模型处理以后,需要将该数字表示形式转换为人可以理解的文本。 原始文本到 token 原始文本转换为token序列的过程通常是在LLM的预处理阶段完成的。 在大型语言模型(LLM)中,tok…

五一营销新趋势:出海品牌如何利用TikTok掀起热潮

数字化时代&#xff0c;TikTok作为当下全球热门的短视频社交平台&#xff0c;以其独特的内容生态和庞大的用户基础&#xff0c;成为出海品牌进行营销的重要阵地。2024年五一国际劳动节即将来临&#xff0c;如何利用TikTok平台进行有效的营销活动&#xff0c;是每个出海品牌都需…

【埋点探针】微信小程序SDK安装

一、下载微信小程序SDK埋点代码 选择Wechat&#xff0c;复制sdk代码 在项目根目录下&#xff0c;创建sdk文件&#xff0c;webfunny.event.js 二、在app.js文件中&#xff0c;引入埋点SDK代码 首先引入sdk代码 require("./webfunny.event.js")引入兼容代码&#x…

TCP传输的粘包问题和各种异常情况

文章目录 粘包问题用分隔符用数字代表长度 TCP传输可能遇到的异常情况进程终止电脑关机正常情况下关机非正常情况关机&#xff08;停电&#xff09;电脑断网 粘包问题 粘包问题其实并不是TCP独有的的问题而是每一个面向字节流都会出现的问题&#xff0c;那么什么是粘包问题呢&…

最近做的一些套利操作

最近做的套利不多&#xff0c;主要是两个品种&#xff1a;全球芯片LOF&#xff0c;标普500LOF&#xff0c;一共盈利1360元。 盈利不多&#xff0c;但是每天我只花了3分钟点几下就赚到了&#xff0c;捡钱就像呼吸一样简单&#xff0c;还要啥自行车&#xff1f; 整理交易记录的…

如何增强Java GCExcel API 的导入和导出性能

前言 GrapeCity Documents for Excel (以下简称GcExcel) 是葡萄城公司的一款服务端表格组件&#xff0c;它提供了一组全面的 API 以编程方式生成 Excel (XLSX) 电子表格文档的功能&#xff0c;支持为多个平台创建、操作、转换和共享与 Microsoft Excel 兼容的电子表格&#xf…

JavaScript —— APIs(三)

一、事件流 &#xff08;一&#xff09;定义 &#xff08;二&#xff09;事件捕获 事件捕获&#xff0c;对话框从大到小弹出&#xff0c;先弹出爷爷&#xff0c;最后弹出儿子 &#xff08;三&#xff09;事件冒泡 冒泡事件&#xff0c;对话框从小到大弹出&#xff0c;先弹出…

【C++】C++11 包装器

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 目录 前言 function包装器 fu…

大模型接口管理和分发系统One API

老苏就职于一家专注于音视频实时交互技术和智能算法的创新企业。公司通过提供全面的 SDK 和解决方案&#xff0c;助力用户轻松实现实时音视频通话和消息传递等功能。尽管公司网站上有详细的文档中心&#xff0c;但在实际开发中&#xff0c;仍面临大量咨询工作。 鉴于此&#x…

单页面首屏优化,打包后大小减少64M,加载速度快了13.6秒

需求背景 从第三方采购的vue2 ElementUI实现的云管平台&#xff0c;乙方说2011年左右就开始有这个项目了&#xff08;那时候有Vue了吗&#xff0c;思考.jpg&#xff09;。十几年的项目&#xff0c;我何德何能可以担此责任。里面的代码经过多人多年迭代可以用惨不忍睹来形容&a…

大模型培训老师叶梓:通过微调提升小型语言模型的复杂推理能力

在人工智能的快速发展中&#xff0c;复杂推理能力的提升一直是研究者们追求的目标。最近&#xff0c;一项发表在arXiv上的研究成果【1】&#xff0c;提出了一种创新的方法&#xff0c;即通过微调小型语言模型&#xff08;LMs&#xff09;&#xff0c;并将其与大型语言模型&…

内旋风铣也挺有意思,不够还没搞透

内旋风铣&#xff0c;这一术语在机械制造业中并不陌生&#xff0c;它代表着一种高效且精确的加工方法。这一技术的名称“内旋风铣”便揭示了其两大核心特点&#xff1a;一是“内”&#xff0c;指的是在工件内部进行加工&#xff0c;通常涉及到难以触及的复杂曲面&#xff1b;二…

C语言趣味代码(二)

1.珠玑妙算 1.1 介绍 《珠玑妙算》(Mastermind)是英国Invicta公司于1973年开始销售的一款益智游戏&#xff0c;据说迄今为止已经在全世界销售了5000万套。《珠玑妙算》于1974年获奖后&#xff0c;在1975年传入美国&#xff0c;1976年leslieH.Autl博士甚至还出版了一本名为The…