一道腾讯面试题——逆序K链表反转

腾讯CSIG腾讯云数据库内核方向-分布式存储,初试算法题

题目

给定如下单链表节点定义:

struct node {
  struct node* next_;
  int val_;
};

给定一个单链表,指定一个整数i,从链表尾部算起,以i个节点为一组进行链表反转操作。组之间保持原链接顺序。如果不够i个节点,也不反转。例如:
原链表为:
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8
指定整数3。则结果链表为:
1 -> 2 -> 5 -> 4 -> 3 -> 8 -> 7 -> 6

是不是很简单,Leetcode经典题,K链表反转,只不过这个是从后往前

方法一:每K个反转

先求出长度,算出可能剩余的部分,跳过开头这部分,对接下来的反转
(1 2) 3 4 5 6 7 8

点击查看代码
#include <iostream>
using namespace std;

struct node {
    struct node* next_;
    int val_;
    node(int val):next_(nullptr), val_(val) {}
};

int countNode(node* head) {
    int cnt = 0;
    node* cur = head;
    while(cur) {
        cnt++;
        cur = cur->next_;
    }
    return cnt;
}


node* reverseK(node* head, int k) {  // 每k个反转一次
    if(head == nullptr)  return nullptr;
    cout << "head: " << head->val_ << endl;  // 有
    
    int cnt = 0;
    node* cur = head, *pre = nullptr, *nxt;
    while(cur && cnt < k) {
        cout << "cnt: " << cnt << " " << cur->val_  << endl;
        nxt = cur->next_;
        cur->next_ = pre;
        pre = cur;
        cur = nxt;
        cnt++;
    }
    // cout << "cur: " << cur->val_ << endl;
    head->next_ = reverseK(cur, k);
    return pre;  //太惨吧,改这一个地方就行了
}

node* reverseList(node* head, int k) {
    int len = countNode(head);
    int last = len % k;
    int cnt = 0;
    node* cur = head, *pre;
    while(cnt < last) {
        cnt++;
        pre = cur;
        cur = cur->next_;
    }
    cout << "cur: " << cur->val_ << endl;  // ok
    pre->next_ = reverseK(cur, k);
    return head;
}

node* createList(int n, int k) {
    node* head = new node(0);
    node* cur = head;

    for(int i = 1;i <= n;i++)  {
        cur->next_ = new node(i);
        cur = cur->next_;
    }
    return head->next_;
}

void printList(node* head) {
    node* cur = head;
    while(cur) {
        cout << cur->val_ << " ";
        cur = cur->next_;
    }
    cout << endl;
}

int main() {
    //int a;
    //cin >> a;
    cout << "Hello World!" << endl;

    node* head = createList(8, 3);

    printList(head);

    head = reverseList(head, 3);

    printList(head);
}

方法二:先整体反转,在以K个为一组反转

有点像“单词翻转”的思路,翻转两次
1 2 3 4 5 6 7 8
8 7 6 5 4 3 2 1
(8 7 6) (5 4 3) (2 1)
(2 1) (5 4 3) (8 7 6)

点击查看代码
#include <iostream>
using namespace std;

struct node {
    struct node* next_;
    int val_;
    node(int val):next_(nullptr), val_(val) {}
};

int countNode(node* head) {
    int cnt = 0;
    node* cur = head;
    while(cur) {
        cnt++;
        cur = cur->next_;
    }
    return cnt;
}

node* reverseAll(node* head) {  // 反转链表
    node* cur = head, *pre = nullptr, *nxt;
    while(cur) {
        nxt = cur->next_;
        cur->next_ = pre;
        pre = cur;
        cur = nxt;
    }
    return pre;
}

node* reverseList(node* head, int k) {  // 逆序K链表反转
    node* dummy = new node(0);
    head =  reverseAll(head);
    node* cur = head, *left = head, *prev;
    while(cur) {
        int cnt = 0;
        while(cur && cnt < k) {  // [left, prev] 为一个组
            cnt++;
            prev = cur;
            cur = cur->next_;
        }
        node* nxt = dummy->next_;  // 每次头插法,插入一个组
        dummy->next_ = left;
        prev->next_ = nxt;

        left = cur;
    }
    return dummy->next_;
}

node* createList(int n, int k) {
    node* head = new node(0);
    node* cur = head;

    for(int i = 1;i <= n;i++)  {
        cur->next_ = new node(i);
        cur = cur->next_;
    }
    return head->next_;
}

void printList(node* head) {
    node* cur = head;
    while(cur) {
        cout << cur->val_ << " ";
        cur = cur->next_;
    }
    cout << endl;
}

int main() {
    //int a;
    //cin >> a;
    cout << "Hello World!" << endl;

    node* head = createList(8, 3);

    printList(head);

    head = reverseList(head, 3);

    printList(head);
}
posted @ 2022-03-01 00:19  Rogn  阅读(102)  评论(0编辑  收藏  举报