【6.6】206. 反转链表 3. 无重复字符的最长子串

206.反转链表

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

ex1:
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

ex2:
输入:head = [1,2]
输出:[2,1]

ex3:
输入:head = []
输出:[]
  1. 迭代法:迭代的方法就是从前往后对链表进行处理,在翻转的过程中要维持一个n指针,一个n+1指针,在处理的过程中首先保存n+2,然后将n+1的next指向n,然后迭代返回n+1和n+2。

迭代法就是从前往后进行处理,这里维护三个指针curr,prev,head,首先curr接着head的值,head向后移动,prev接着curr的值,curr然后跟上head,最后prev保存了所有的数值,所以返回prev。换句话说正因为是从前往后处理的,所以返回的值肯定是要逐步增长的,只有是prev,不可能是head,curr。(9.1)

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
		ListNode* prev = nullptr;
        ListNode* curr = head;
        
        while(curr) {
            ListNode* next = curr->next; // 这里就是保存n+2的过程
            curr->next = prev; // 这里将n+1指向n
            prev = curr; // 迭代返回prev=n+1,之前是prev=n
            curr = next; // 迭代返回curr=n+2,之前是curr=n+1
        }
        return prev;
    }
};
  1. 递归法:使用递归法返回newhead,然后每次仅对当前节点进行处理,返回的同样是newhead。并且在处理的过程中需要将head next指向nullptr避免造成环。

优于递归法每次都要用到返回值,所以函数的返回值必定是newhead,而head指针就需要留下来处理队尾元素。使用reverse(head->next)后返回的是反转好的链表(类似的,最终返回的也是整个反转好的链表),所以会从1->2->3->4->5->nullptr,head为1,newhead=reverse(head->next),变为1->2<-3<-4<-5。然后将head的尾部进行处理即可。

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;
    }
};
  • 如果不加head->next = nullptr;这句代码会让链表中出现环,并且会输出一个链表入口处有环的链表
  • 如果输入为有环链表,对于迭代法可以输出翻转后的循环链表,对于递归法会死循环
  1. 头插法
    ListNode* reverseList(ListNode* head) {
        if(head==nullptr || head->next==nullptr) return head;
        ListNode* tmp = new ListNode();
        ListNode* ret = new ListNode();

        tmp = head->next;
        head->next = nullptr;
        ret = head;
        head = tmp;

        while(head->next) {
            tmp = head->next;
            head->next = ret;
            ret = head;
            head = tmp;
        }
        head->next = ret;
        
        return head;
    }

3. 无重复字符的最长子串

给定一个字符串 s ,请你找出其中不含有重复字符的最长子串的长度。

输入: s = "abcabcbb"
输出: 3
  1. 双指针法,没重复就在查找表中+1,右指针向右移动一位,重复就在查找表中对左指针的符号-1,然后左指针向右移动一位
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int symbol[1000] = {0};
        if(s.size() == 0 || s.size() == 1) return s.size(); 
        int left = 0;
        int ret = 0;
        for(int i = 0; i < s.size(); i++) {
            if(symbol[s[i]] == 0) {
                ret = max(ret, i - left + 1);
                symbol[s[i]] += 1;
            } else {
                symbol[s[left]] -= 1;
                left += 1;
                i -= 1;
            }
        }
        return ret;
    }
};
  1. 使用unordered_set的find,erase,insert的方法便捷实现重复的情况
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        if(s.size() == 0) return 0;
        unordered_set<char> lookup;
        int ret = -1;
        int ptr = 0;
        for(int i=0; i<s.size(); i++) {
            while (lookup.find(s[i]) != lookup.end()){
                lookup.erase(s[ptr]);
                ptr++;
            }
            ret = max(ret,i-ptr+1);
            lookup.insert(s[i]);
        }
        return ret;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值