連結串列中節點每k 個一組翻轉
阿新 • • 發佈:2021-02-06
題目:
將給出的連結串列中的節點每k個一組翻轉,返回翻轉後的連結串列
如果連結串列中的節點數不是k的倍數,將最後剩下的節點保持原樣
你不能更改節點中的值,只能更改節點本身。
要求空間複雜度 O(1)
例如:
給定的連結串列是1→2→3→4→5
對於 k=2, 你應該返回 2→1→4→3→5
對於 k=3, 你應該返回 3→2→1→4→5
思路分析:
連結串列需要每k個就翻轉一次,那需要用到兩個函式進行兩次操作:
- 一個是用來對連結串列進行分段,並確定最後一次是否滿足k個節點;
- 一個是用來最小段連結串列進行翻轉,並將新的小段連結串列頭返回;
兩個操作可以分別用兩個函式封裝,也可以放到一個函式中。
方法一:可以先統計連結串列的長度,然後根據長度進行分段,再呼叫翻轉的功能
方法二:通過遞迴的方法,head記錄小段的頭,cur記錄下一個小段的起點,或是結束點的下一個節點。
因為翻轉的函式都一樣的,這裡只提供方法二的程式碼:
#include <stdio.h> #include <stdlib.h> typedef struct node { int value; struct node* next; } list_node; list_node* reverse(list_node* head, list_node* tail) { list_node* pre = NULL; list_node* next = NULL; while (head != tail) { next = head->next; head->next = pre; pre = head; head = next; } return pre; } list_node* reverse_k_group(list_node* head, int k) { list_node* cur = head; list_node* new_head = NULL; for (int i = 0; i < k; ++i) { if (!cur) { return head; } cur = cur->next; } new_head = reverse(head, cur); head->next = reverse_k_group(cur, k); return new_head; } void print(list_node* head, int k) { list_node* cur = head; while (cur) { if (cur != head) { printf("->"); } else { printf("k = %d: ", k); } printf("%d", cur->value); cur = cur->next; } printf("\n"); } void test10() { list_node* head = NULL; list_node* cur = NULL; for (int i = 0; i < 5; ++i) { list_node* node = (list_node*)malloc(sizeof(list_node)); node->value = i + 1; node->next = NULL; if (!head) { head = node; } if (!cur) { cur = node; } else { cur->next = node; cur = node; } } print(head, 1); head = reverse_k_group(head, 2); print(head, 2); }
執行結果: