刷题指南-0

第一题:两数相加(简单题,主要是为了复习链表)

(不会吧不会吧,真的有人这题都能提交错吗,哦,原来是我阿,那没事了)



题目描述:

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。



示例图:


测试用例:



问题分析:主要是模仿大数相加,用链表的方式来模拟计算机做加法运算。

可能考虑出现解决该问题:链表长度不一样,我们需要先遍历完较小的链表加和,再计算进位,再对较长的链表进行剩余的遍历,我们设置一个指针用来遍历,一个头节点用来返回整个链表。

(这里手画图)

C++(很不熟悉,基本都用python了,但是博士申请得上机选定用c++,只能硬磕)

代码如下:

/**

* Definition for singly-linked list.

* struct ListNode {

*    int val;

*    ListNode *next;

*    ListNode() : val(0), next(nullptr) {}

*    ListNode(int x) : val(x), next(nullptr) {}

*    ListNode(int x, ListNode *next) : val(x), next(next) {}

* };

*/classSolution{public:

    ListNode*addTwoNumbers(ListNode* l1, ListNode* l2){

        //从这里看起

        ListNodejg(0);//创建一个头节点

        ListNode *l3 = &jg;//创建一个遍历指针

        int flag; //设置进位

        flag=0;//初始化进位

        while(l1 !=nullptr && l2 !=nullptr) //如果俩链表都不为空

        {

            int s=0;

            s=l1->val+l2->val+flag; //求和并累加进位

            cout<<l1->val<<endl;

            cout<<l2->val<<endl;

            cout<<"这里是打印每俩个数的加和"<<endl;

            cout<<s<<endl;

            cout<<"结束"<<endl;

            flag=s>=10? 1:0;

            l3->next=new ListNode(s%10);

            cout<<"这里是打印对于每一个链表的下一个数"<<endl;

            cout<<l3->next->val<<endl;

            cout<<"这里是打印对于每一个链表的下一个数"<<endl;

            l1=l1->next;

            l2=l2->next;

            l3=l3->next;

            //cout<<l3->val<<endl;        }

        while(l1 !=nullptr) //已经循环完最小的链表了,我们需要看看剩下的链表在哪里,如果在l1里,则加完它。

        {

            int s=0;

            s=l1->val+flag;

            l3->next=new ListNode(s%10);

            flag=s>=10?1:0;

            l1=l1->next;

            l3=l3->next;

        }

        while(l2 !=nullptr)//已经循环完最小的链表了,我们需要看看剩下的链表在哪里,如果在l2则加完它。

        {

            int s=0;

            s=l2->val+flag;

            l3->next=new ListNode(s%10);

            flag=s>=10?1:0;

            l2=l2->next;

            l3=l3->next;

        }

        if(flag) //如果加到最后,还有一个进位怎么办,我们还需要创建一个节点来保存它

        {

            l3->next=new ListNode(flag);

        }

        return jg.next;//返回头节点的next

    }

};



第二题 寻找两个正序数组的中位数

暴力合并求中值很简单,但是光看题解的方法我就看了一个小时才会(我好菜)



题目描述:给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的中位数。

进阶:你能设计一个时间复杂度为 O(log (m+n)) 的算法解决此问题吗?

测试用例:



首先看非进阶的方式,合并排序,没有什么好说的,给出实现方法。因为这个题目它不会出现重复值,所以我们也没有必要去重。

python 实现:

class Solution:

    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:        

        def findMid(num):

            if len(num) % 2 == 0: //如果是偶数数组

                return (num[int(len(num)/2)] + num[int((len(num))/2-1)]) / 2  //取中间俩数求和

            else :

                return num[int((len(num)-1)/2)] * 2 / 2  //取中间一个数

        num = sorted(nums1 + nums2) //数据相加排序就可以了

        return findMid(num) //返回结果

python的好处在于可以直接相加 nums1 + nums2 就可以合并数组,如果是C++,则需要我们开一个大数组,设置俩标记符i和j,从i=0和j=0开始,每一次比较俩数的大小,小的数就放进新数组,并且小的数组的下标++。

简单的方法直接说完到难的方法



二分方法(听说是408真题??)

可以看题解一大堆文字哔哔哔,但是基本还是摸不着头脑,但是可以这样理解。

首先我们有俩个有顺序的数组(从小到大)

分别为N1=[1,2,3,4]

和N2=[3,5,7,9,10]

我们可以使用一个小技巧

我们分别找第 (m+n+1) / 2 个元素,和 (m+n+2) / 2 个,然后求其平均值即可,这对奇偶数组均适用。

其中m为N1的长度,n为N2的长度,分别为4和5

我们来验证一下,对于N1和N2的合并数组N3=[1,2,3,3,4,5,7,9,10]

 (m+n+1) / 2=5    (m+n+2) / 2=int(5.5)=5

对于奇数组中位数第五个,验证无问题(你非要我数学证明那我就没办法了qaq)

下一步,我们可以通过找第k小数的方法来解决它,对于上面的例子,我们用找第5小数来计算,

//找第k小数

 public int find(int[] nums1, int i, int[] nums2, int j, int k){

        if( i >= nums1.length) return nums2[j + k - 1];//i是nums1的起始标识,如果过界了,我们需要从nums2里找中位数,直接取j + k - 1,为什么?我也不知道大佬解惑

        if( j >= nums2.length) return nums1[i + k - 1];//j是nums1的起始标识,如果过界了,我们需要从nums1里找中位数,直接取i + k - 1,为什么?我也不知道大佬解惑

        //k为1时,指的是迭代到边界了,我们直接返回俩数值最小值

        if(k == 1){

            return Math.min(nums1[i], nums2[j]);

        }

        int midVal1 = (i + k / 2 - 1 < nums1.length) ? nums1[i + k / 2 - 1] : 10000000;

        int midVal2 = (j + k / 2 - 1 < nums2.length) ? nums2[j + k / 2 - 1] : 10000000;

        if(midVal1 < midVal2){

            return find(nums1, i + k / 2, nums2, j , k - k / 2);

        }else{

            return find(nums1, i, nums2, j + k / 2 , k - k / 2);

        }        

    }

上面代码的思路如果同学(菜鸡申请py交易)们想理解的话可以这么理解,每次都会计算俩个数组的中间值,然后把中间值对比,如果中间值小的数组的中间值前一半的部分就会丢弃(通过什么方式丢弃 i+k/2或者j+k/2),然后剩下的接着比,一直到i或j越界为止。或者k==1为止。

对我来说,记住findkth()函数就很好了,再理解原理(相当于走了一条捷径)

(但是总所周知的是,所有捷径都有代价,读书如此,做人亦是如此)

此题结束。



第三题 最长回文子串(动态规划,Manacher 算法)

中等难度题目

其实主要动态规划做的不够多,不知道怎么去匹配问题。

这里先偷一张图,看看大佬的动态规划思路是什么样的

大佬链接在这里

https://leetcode-cn.com/problems/longest-palindromic-substring/solution/zhong-xin-kuo-san-dong-tai-gui-hua-by-liweiwei1419/


问题分析:dp[i][j] 表示子串 s[i..j] 是否为回文子串,这里子串 s[i..j] 定义为左闭右闭区间,可以取到 s[i] 和 s[j]。

dp二维数组里一共有俩个值,分别为true和false,分别代表s[i..j]是否为回文数。

分类思考

(1)假如s[i..j]的长度只有1,那它肯定是回文数

(3)假如s[i..j]的长度有大于等于2(>=2),如果dp[i+1][j-1]是回文数,并且,注意是并且,对于dp[i+1][j-1]新加入的数s[i]==s[j],那么dp[i][j]是true,s[i..j]是回文数。

下面开始填表(没有时间画图,我就只能偷了(什么,读书人的事情不算偷,那没事了))

下面直接给其他人代码了。(我会自己补上的,qaq)(主要是太菜了,光看理论就看了挺久)

class Solution:

    def longestPalindrome(self, s: str) -> str:

        size = len(s) #获取s的值,没有什么问题

        if size < 2:

            return s #如果小于2,肯定是回文数,我们直接返回就可以了。

        dp = [[False for _ in range(size)] for _ in range(size)] #构建二维数组,附上初值

        max_len = 1 //记录最大长度

        start = 0

        for i in range(size): //初始化

            dp[i][i] = True  //因为每一个s[i][i]的长度都是1,所以都是回文数

        for j in range(1, size)://第一个循环

            for i in range(0, j): //第二个循环

                if s[i] == s[j]:

                    if j - i < 3:

                        dp[i][j] = True

                    else:

                        dp[i][j] = dp[i + 1][j - 1]

                else:

                    dp[i][j] = False

                if dp[i][j]: //如果dp[i][j]==true

                    cur_len = j - i + 1 //每次更新就更新一下最大长度

                    if cur_len > max_len:

                        max_len = cur_len 

                        start = i   //更新start的起始位置

        return s[start:start + max_len] //返回回文串

第一个方法结束。



第二个方法Manacher算法

从每个点出发,向俩边寻找对比,最后p里最大的值就是我们要的,最大值位置对应的坐标为回文中心。

class Solution:

    # Manacher 算法

    def longestPalindrome(self, s: str) -> str:

        # 特判

        size = len(s)

        if size < 2:

            return s

        # 得到预处理字符串

        t = "#"

        for i in range(size):

            t += s[i]

            t += "#"

        # 新字符串的长度

        t_len = 2 * size + 1

        # 当前遍历的中心最大扩散步数,其值等于原始字符串的最长回文子串的长度

        max_len = 1

        # 原始字符串的最长回文子串的起始位置,与 max_len 必须同时更新

        start = 0

        for i in range(t_len):

            cur_len = self.__center_spread(t, i)

            if cur_len > max_len:

                max_len = cur_len

                start = (i - max_len) // 2

        return s[start: start + max_len]

    def __center_spread(self, s, center):

        size = len(s)

        i = center - 1

        j = center + 1

        step = 0

        while i >= 0 and j < size and s[i] == s[j]:

            i -= 1

            j += 1

            step += 1

        return step

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,029评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,238评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,576评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,214评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,324评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,392评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,416评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,196评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,631评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,919评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,090评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,767评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,410评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,090评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,328评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,952评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,979评论 2 351

推荐阅读更多精彩内容