0510刷题

这篇博客主要介绍了LeetCode中关于链表的操作,包括两两交换链表中的节点,以及查找链表的相交节点和环形链表。同时,讨论了如何找出字符串的字母异位词,包括两种不同的解决方案,一种基于哈希,另一种利用滑动窗口。
摘要由CSDN通过智能技术生成

0510刷题

LeetCode 24. 两两交换链表中的节点

LeetCode 24. 两两交换链表中的节点
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* dummyHead = new ListNode(0); // 设置一个虚拟头结点
        dummyHead->next = head; // 将虚拟头结点指向head,这样方面后面做删除操作
        ListNode* cur = dummyHead;
        while(cur->next != nullptr && cur->next->next != nullptr) {
            ListNode* tmp = cur->next; // 记录临时节点
            ListNode* tmp1 = cur->next->next->next; // 记录临时节点

            cur->next = cur->next->next;    // 步骤一
            cur->next->next = tmp;          // 步骤二
            cur->next->next->next = tmp1;   // 步骤三

            cur = cur->next->next; // cur移动两位,准备下一轮交换
        }
        return dummyHead->next;
    }
};

思路:

这道题目正常模拟就可以了。

建议使用虚拟头结点,这样会方便很多,要不然每次针对头结点(没有前一个指针指向头结点),还要单独处理。

接下来就是交换相邻两个元素了,此时一定要画图,不画图,操作多个指针很容易乱,而且要操作的先后顺序

初始时,cur指向虚拟头结点,然后进行如下三步:

24.两两交换链表中的节点1

操作之后,链表如下:

24.两两交换链表中的节点2

看这个可能就更直观一些了:

24.两两交换链表中的节点3

面试题 02.07. 链表相交

面试题 02.07. 链表相交
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* tmp1=headA;
        ListNode* tmp2=headB;

        while(tmp1!=tmp2)
        {
            if(tmp1) tmp1=tmp1->next;
            else tmp1=headB;

            if(tmp2) tmp2=tmp2->next;
            else tmp2=headA;
        }

        return tmp1==NULL?NULL:tmp1;
    }
};

也即:

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *curA = headA, *curB = headB;
        while (curA != curB) {
            curA = curA != nullptr ? curA->next : headB;
            curB = curB != nullptr ? curB->next : headA;
        }
        return curA;
    }
};

LeetCode 142. 环形链表 II

LeetCode 142. 环形链表 II
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* slow=head;
        ListNode* fast=head;

        while(fast!=NULL&&fast->next!=NULL)
        {
            slow=slow->next;
            fast=fast->next->next;
            if(slow==fast)
            {
                slow=head;
                while(slow!=fast)
                {
                    slow=slow->next;
                    fast=fast->next;
                }
                return slow;
            }   
        }
        return NULL;
    }
};

LeetCode 49. 字母异位词分组

LeetCode 49. 字母异位词分组

自己的解法:思路正确,但是时间复杂度为O(n),数据量过大时超时了。

class Solution {
public:
    bool cmp(string s,string t)
    {
        int num[26]={0};
        for(auto &com:s) num[com-'a']++;
        for(auto &com:t) num[com-'a']--;

        for(auto &c:num)
        {
            if(c!=0) return false;
        }
        return true;
    }

    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        vector<vector<string>> result;

        int n=strs.size();
        vector<int> flag(n,1);
        for(int i=0;i<strs.size();++i)
        {
            vector<string> tmp;
            if(flag[i]!=0)
            {
                tmp.push_back(strs[i]);
                flag[i]=0;
                for(int j=i+1;j<strs.size();++j)
                {
                    if(flag[j]!=0&&cmp(strs[i],strs[j])) 
                    {
                        tmp.push_back(strs[j]);
                        flag[j]=0;
                    }
                }
            }
            if(tmp.size()!=0) result.push_back(tmp);            
        }
        return result;
    }
}; 

参考答案的做法:

由于互为字母异位词的两个字符串包含的字母相同,因此对两个字符串分别进行排序之后得到的字符串一定是相同的,故可以将排序之后的字符串作为哈希表的键。原来的字符串为str,重新排序之后为key,如果mp中有key的键值,则将str压入key键值对应的vector中。

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        unordered_map<string, vector<string>> mp;
        for (string& str: strs) {
            string key = str;
            sort(key.begin(), key.end());
            mp[key].emplace_back(str);
        }
        vector<vector<string>> ans;
        for (auto it = mp.begin(); it != mp.end(); ++it) {
            ans.emplace_back(it->second);
        }
        return ans;
    }
};

也即:

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        unordered_map<string,vector<string>> umap;
        for(auto &str:strs)
        {
            string tmp=str;
            sort(tmp.begin(),tmp.end());
            umap[tmp].push_back(str);
        }

        vector<vector<string>> result;
        for(auto &c:umap)
        {
            result.push_back(c.second);
        }
        return result;
    }
};

LeetCode 438. 找到字符串中所有字母异位词

LeetCode 438. 找到字符串中所有字母异位词

方法:哈希+滑动窗口法

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        int sLen = s.size(), pLen = p.size();

        if (sLen < pLen) return {};

        vector<int> result;
        vector<int> sCount(26);
        vector<int> pCount(26);
        //统计长度为pLen的字符串中,各个小写字母出现的次数
        for (int i = 0; i < pLen; ++i) 
        {
            ++sCount[s[i] - 'a'];
            ++pCount[p[i] - 'a'];
        }
        //如果相等,则0符合要求
        if (sCount == pCount) 
        {
            result.emplace_back(0);
        }

        //长度为pLen的窗口向右滑动
        //移出的元素个数--
        //移入的元素个数++
        for (int i = 0; i < sLen - pLen; ++i) 
        {
            --sCount[s[i] - 'a'];
            ++sCount[s[i + pLen] - 'a'];

            //相等,则push_back进result
            if (sCount == pCount) 
            {
                result.emplace_back(i + 1);
            }
        }

        return result;
    }
};

说明:

当字符串 s 的长度小于字符串 p 的长度时,字符串 s 中一定不存在字符串 p 的异位词。

由于子串是连续的,且异位词不会改变字符串中每个字符的个数,所以只有当两个字符串每个字符的个数均相等时,一个字符串才是另一个字符串的异位词。

使用两个数组 sCount和 pCount分别统计 s 和 p 中字母的个数。

由于需要遍历的子串 p 长度均为 pLen ,我们可以使用一个固定长度为 pLen 的滑动窗口来维护 sCount:滑动窗口每向右滑动一次,就多统计一次进入窗口的字符,少统计一次离开窗口的字符。然后,判断 sCount是否与 pCount相等,若相等则意味着 p 的异位词之一是 s 的子串。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值