2021-08-02

1.反转链表
在这里插入图片描述
使用递归的方法,对于递归算法,最重要的就是明确递归函数的定义。具体来说,我们的reverse函数定义是这样的:输入一个节点head,将「以head为起点」的链表反转,并返回反转之后的头结点, 显然如果将head->next作为参数执行,就会将以head->next为头节点的链表反转,而头节点没有被反转。之后只要将头节点反转就可以了
在这里插入图片描述

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(!head || !head->next) return head;
        ListNode* newHead = reverseList(head->next);
        head->next->next = head;
        head->next = nullptr;
        return newHead;

    }
};

2.反转链表 II

在这里插入图片描述
这题是上面题的变式,该题只需反转部分链表
同样也是递归, 要解决该题先解决反转链表前n个节点的问题。
思路和反转整个链表差不多,只要稍加修改1、递归出口,变为n == 1 2.之前head->next直接为空,因为后面所有节点都反转了,只剩下头节点了,但是现在head节点不一定是最后一个节点了,所以要记录后驱节点 successor (第 n + 1 个节点), 反转后将head 接上

反转链表前n个节点

	ListNode* successor;
    ListNode* reverseN(ListNode* head, int n){
        if(n == 1){
            successor = head->next;
            return head;
        }
        ListNode* newHead = reverseN(head->next, n - 1);
        head->next->next = head;
        head->next = successor;
        return newHead;
    }

现在来解决这个题目, 反转区间 [m , n] (m 从 1 开始)的节点。
首先如果m == 1 ,那不就相当于反转链表前n个元素嘛
那么 m != 1时, 如果把head 的索引视为1, 那么我们是想从第 m 个元素开始反转对吧;如果把head->next 的索引视为1呢?那么反转的区间应该时从 m - 1个元素开始的;那么对与head->next->next呢…

这就是递归思想,代码如下

class Solution {
public:
    ListNode* successor;
    ListNode* reverseN(ListNode* head, int n){
        if(n == 1){
            successor = head->next;
            return head;
        }
        ListNode* newHead = reverseN(head->next, n - 1);
        head->next->next = head;
        head->next = successor;
        return newHead;
    }
    ListNode* reverseBetween(ListNode* head, int left, int right) {
        if(left == 1){
            return reverseN(head, right);
        }
        head->next = reverseBetween(head->next, left-1, right-1);
        return head;

    }
};

3. K个一组翻转链表

在这里插入图片描述
在这里插入图片描述
之前的题目都是用递归来写的,这个用迭代的方法来解
1.先翻转以 head 开头的 k 个元素
2.将第 k + 1 个元素作为 head 递归调用 reverseKGroup 函数
3. 将上述两个结果连接起来

翻转区间 [ a, b)的节点 注意是左闭右开

ListNode* reverse(ListNode*a, ListNode*b){
        ListNode* pre;
        ListNode* cur;
        ListNode* nxt;
        pre = nullptr; cur = a;nxt = a;
        while(cur != b){
            nxt = cur->next;
            cur->next = pre;
            pre = cur;
            cur = nxt;
        }
        return pre;
    }

reverserKGroup 函数代码如下:

ListNode* reverseKGroup(ListNode* head, int k) {
        if(!head) return nullptr;
        ListNode* a;
        ListNode* b;
        b = head;
        a = head;
        for(int i = 0; i < k; i++){
        	// 不足 k 个, 不需要翻转
            if(!b) return head; 
            b = b->next;
        }
        // 翻转前 k 个节点
        ListNode* newHead = reverse(a, b);
        // 递归反转后续链表并连接起来
        a->next = reverseKGroup(b, k);

        return newHead;

    }

4.最长回文字串
在这里插入图片描述
寻找回文串的问题核心思想是:从中间开始向两边扩散来判断回文串
但是呢,回文串的长度可能是奇数也可能是偶数,如果是abba这种情况,没有一个中心字符,所以我们可以修改一下:

for 0 <= i < len(s):
    找到以 s[i] 为中心的回文串
    找到以 s[i] 和 s[i+1] 为中心的回文串
    更新答案

但这样做,索引会越界,等会会处理

先实现一个函数来寻找最长回文串,这个函数是有点技巧的
传入两个指针 l 和 r , 可以同时处理回文串长度为奇数和偶数的情况

string findlongest(string s, int l, int r){
		// 防止索引越界
        while(l >= 0 && r < s.length() && s[l] == s[r]){
            l--;
            r++;
        }
        return s.substr(l + 1, r - l - 1 );
    }

最终代码:

string longestPalindrome(string s) {
        string res;
        for(int i = 0; i < s.size(); i++){
            string s1 = findlongest(s,i, i);
            string s2 = findlongest(s, i, i + 1);
            res = res.size() > s1.size()? res:s1;
            res = res.size() > s2.size()? res:s2;
        }

        return res;

    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值