笔试算法训练day3

AcWing&Leetcode好题分享(入门级)day3


前言

今天是算法小学徒分享自己在Acwing&leetcode平台准备笔试面试刷题过程中觉得质量高的题目的第三天,下面配有作者的讲解,希望能够帮助到大家

一、前置知识

滚动数组
滚动数组是一种能够在动态规划中降低空间复杂度的方法,是动态规划(Dynamic Programming,DP)中的一种编程思想,简单地理解就是让数组滚动起来,每次都使用固定的几个存储空间。来达到压缩,节省存储空间的作用。可起到起到优化突间的作用,主要应用在递推或动态规划中(如01背包问题)。而且DP题目是一个自底向上的扩展过程,我们常常需要用到的是连续的解,前面的解往往可以舍去。所以用滚动数组优化是很有效的。利用滚动数组的话在N(个数,项数)很大的情况下可以达到压缩存储的作用。

二、1.斐波那契数列

输入一个整数 n ,求斐波那契数列的第 n 项。

假定从 0 开始,第 0 项为 0。

数据范围
0≤n≤39
样例
输入整数 n=5

返回 5
题目分析:简单介绍一下这题面试中常考的题目斐波那契数列,首先简单介绍一下斐波那契数列是什么:

a0=0,a1=1,an=an−1+an−2,求an是多少

我们可以看到这题的数据范围非常小,可以直接用复杂度为O(n)的递推来做
具体解法:先定义两个变量a,b,分别表示第n−1项和第n项。且定义c=a+b来表示第 n+1项,然后让a,b滚动地顺次往后移一位(滚动数组解法)

class Solution {
public:
    int Fibonacci(int n) {
        int a=0,b=1;
        while(n--)
        {
            int c=a+b;
            a=b,b=c;
        }
        return a;
    }
};

2.替换空格

请实现一个函数,把字符串中的每个空格替换成"%20"。

数据范围
0≤ 输入字符串的长度 ≤1000。
注意输出字符串的长度可能大于 1000。

样例
输入:“We are happy.”

输出:“We%20are%20happy.”
题目分析:

这题用C++做会很方便,我们可以从前往后枚举原字符串;
如果遇到空格,则在string类型的答案中添加"%20";
如果遇到其他字符,则直接将它添加在答案中;
class Solution {
public:
    string replaceSpaces(string &str) {
        string res;
        for(auto x:str)
            if (x==' ')
                res+="%20";
            else
                res+=x;
        return res;
    }
};

3.求1+2+…+n

求 1+2+…+n,要求不能使用乘除法、for、while、if、else、switch、case 等关键字及条件判断语句 (A?B:C)。

数据范围
1≤n≤1000。

样例
输入:10

输出:55
题目分析:

(递归) 时间复杂度O(n)
这题最直接的想法就是用递归,sum(n)=n+sum(n-1),
但是要注意终止条件,由于求的是1+2++n的和,
所以需要在n=0的时候跳出递归,但是题目要求不能使用if,while等分支判断,
所以可以考虑利用&&短路特性运算来终止判断。
class Solution {
public:
    int getSum(int n) 
    {
        int res=n;
        n>0&&(res+=getSum(n-1));
        return res;
    }
};

4.在O(1)时间删除链表结点

给定单向链表的一个节点指针,定义一个函数在O(1)时间删除该结点。

假设链表一定存在,并且该节点一定不是尾节点。

数据范围
链表长度 [1,500]。

样例
输入:链表 1->4->6->8
删掉节点:第2个节点即6(头节点为第0个节点)

输出:新链表 1->4->8

(链表) O(1)
由于是单链表,所以不能找到前驱节点,所以我们不能按常规方法将该节点删除。
我们可以换一种思路,将下一个节点的值复制到当前节点,然后将下一个节点删除即可。

时间复杂度
只有常数次操作,所以时间复杂度是O(1)
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void deleteNode(ListNode* node) {

        auto p=node->next;//auto自动定义数据类型

        node->val = p->val;
        node->next = p->next;
        // 这两步的作用就是将 *(node->next) 赋值给 *node,所以可以合并成一条语句:
        // *node = *(node->next);
        
        delete p;
    }
};

总结

链表是一种线性的数据结构,由分散的节点组成,而每个节点包含数据元素和指向下一个节点的链接(指针)
链表特性:
1.链表是线性表(Linear List)
2.链表节点在内存中存储的空间不连续
3.可以动态地增加或减少元素

链表对比数组

内存空间存储结构:

数组:存储在一组连续的内存空间中
链表:节点分散在各自不同的内存空间中

调整各自的大小

数组:增加或减少元素个数,大多需要重新分配一整块连续的内存空间,然后复制原有数据
链表:节点不需要连续地存储在一块地方,增加和删除节点,非常方便

内部随机访问

数组:可以通过下标地址随机访问数组
链表:只能通过一个节点一个节点轮询,效率低

链表组成元素

节点 Node
数据
指向下一个节点的链接或指针
头 Head
尾 Tail

链表是一种重要的数据结构,在面试中常用来考察应聘者的基本功,希望大家可以在日常学习中多多练习链表这种线性的数据结构,这种数据结构可以用在很多地方,比如内核的消息队列、缓存管理、跳表,B+ 树等。
在面试过程中你能干脆利落地解决链表问题,可以说明你具有一定的算法思想,同时证明了你的编程功底。

评论 37
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

算法小学徒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值