LeetCode——数据结构训练(链表十题)
大部分分类都有了——题号目录网址
对应题号到LeetCode搜索
简单题要理解头结点,头结点是指向节点地址,并没有存放实际内容,主要是方便插入等操作,具体可以百度
160. 找出两个链表的交点(简单题)
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *pA = headA, *pB = headB;
while(pA!=pB){
pA = pA!=NULL ? pA->next:headB;
pB = pB!=NULL ? pB->next:headA;
}
return pA;
}
};
206. 链表反转(简单题)
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* phead = nullptr; // 第一个指向空
while(head!=nullptr){
ListNode* next = head->next;
head->next = phead;
phead = head;
head = next;
}
return phead;
}
};
21. 归并两个有序的链表(简单题)
// 大部分简单题都有递归的方法,可以去参考官方代码
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* newHead = new ListNode(-1);
ListNode* pre = newHead;
while(l1!=nullptr && l2!=nullptr){
if(l1->val<l2->val){
pre->next = l1;
pre = pre->next;
l1 = l1->next;
}
else{
pre->next = l2;
pre = pre->next;
l2 = l2->next;
}
}
pre->next = l1!=nullptr?l1:l2;
return newHead->next;
}
};
83. 从有序链表中删除重复节点(简单题)
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if(!head){
return head;
}
ListNode* l1 = head;
while(l1->next){
if(l1->val==l1->next->val){
l1->next = l1->next->next;
}
else{
l1 = l1->next;
}
}
return head;
}
};
19. 删除链表的倒数第 N 个结点(中等题)
// 一次循环解决,双指针的想法
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* first = head;
ListNode* last = head;
while(n--){
first = first->next;
}
// 判断是否删除第一个元素,即只有一个元素
if(first){
ListNode* pre = last;
while(first){
pre = last;
first = first->next;
last = last->next;
}
pre->next = last->next;
delete last;
}
else{
ListNode* q = head;
head = q->next;
delete q;
}
return head;
}
};
24. 交换链表中的相邻结点(中等题)
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* one = dummyHead;
while (one->next != nullptr && one->next->next != nullptr) {
// one two three 分别代表三个节点,two和three互相交换
ListNode* two = one->next;
ListNode* three = one->next->next;
one->next = three;
two->next = three->next;
three->next = two;
one = two;
}
return dummyHead->next;
}
};
445. 链表求和表(中等题)
不反转链表的方法,官网感觉比较绕
下面是用栈来实现
// 如果输入链表不能修改该如何处理?换句话说,你不能对列表中的节点进行翻转。
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
stack<int> s1,s2;
while(l1){
s1.push(l1->val);
l1 = l1->next;
}
while(l2){
s2.push(l2->val);
l2 = l2->next;
}
ListNode* res = nullptr;
int carry = 0;
while(!s1.empty() || !s2.empty() || carry!=0){
int sum = (s1.empty()?0:s1.top()) + (s2.empty()?0:s2.top()) + carry;
if(!s1.empty()) s1.pop();
if(!s2.empty()) s2.pop();
carry = sum/10;
ListNode* node = new ListNode(sum%10);
node->next = res;
res = node;
}
return res;
}
};
234. 回文链表(简单题)
class Solution {
public:
bool isPalindrome(ListNode* head) {
if (head == nullptr) {
return true;
}
// 找到前半部分链表的尾节点并反转后半部分链表
ListNode* firstHalfEnd = endOfFirstHalf(head);
ListNode* secondHalfStart = reverseList(firstHalfEnd->next);
// 判断是否回文
ListNode* p1 = head;
ListNode* p2 = secondHalfStart;
bool result = true;
while (result && p2 != nullptr) {
if (p1->val != p2->val) {
result = false;
}
p1 = p1->next;
p2 = p2->next;
}
// 还原链表并返回结果
firstHalfEnd->next = reverseList(secondHalfStart);
return result;
}
ListNode* reverseList(ListNode* head) {
ListNode* prev = nullptr;
ListNode* curr = head;
while (curr != nullptr) {
ListNode* nextTemp = curr->next;
curr->next = prev;
prev = curr;
curr = nextTemp;
}
return prev;
}
ListNode* endOfFirstHalf(ListNode* head) {
ListNode* fast = head;
ListNode* slow = head;
while (fast->next != nullptr && fast->next->next != nullptr) {
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
};
725. 分隔链表(中等题)
class Solution {
public:
vector<ListNode*> splitListToParts(ListNode* root, int k) {
ListNode* curr = root;
// 计算长度
int n = 0;
while (curr != nullptr)
{
curr = curr->next;
++n;
}
// 长度和余数
int len = n / k;
int mod = n % k;
vector<ListNode*> res(k, nullptr);
// 重置curr为root起点
curr = root;
for (int i = 0; i < k; ++i)
{
ListNode* head = curr;
// 有余数情况,保证前面每个分组多1,所以i<mod
// 也可以通过mod--来实现
// int currLen = len + ((i < mod) ? 1 : 0);
int currLen = len + (mod-->0 ? 1 : 0);
// 遍历去构建走到当前链表的尾部
for (int j = 0; j < currLen - 1; ++j)
{
if (curr != nullptr)
{
curr = curr->next;
}
}
// 额外去设置curr->next = nullptr
if (curr != nullptr)
{
ListNode* temp = curr;
curr = temp->next;
temp->next = nullptr;
}
// cout << i << " " << ((head != nullptr) ? head->val : -1) << endl;
res[i] = head;
}
return res;
}
};
328. 奇偶链表(中等题)
class Solution {
public:
ListNode* oddEvenList(ListNode* head) {
if(head == nullptr ||head->next==nullptr || head->next->next==nullptr) return head;
ListNode* odd = head;
ListNode* even = head->next;
ListNode* evenhead = even;
while(even!=nullptr && even->next!=nullptr){
odd->next = even->next;
odd = odd->next;
even->next = odd->next;
even = even->next;
}
odd->next = evenhead;
return head;
}
};
2.总结
链表的数据结构,主要理解头指针,把基本头插法这些搞定,题目大部分都还好。