数日前に暴行バイトをインタビューする友人、インタビュアーは彼に尋ねたリスト彼らが来て、私に尋ねた、アルゴリズムの質問に関連しますが、うちの中で、彼は行っていなかった、私はかなり良い感じ、この質問、という点で取ります話。
タイトル
これは実際には歪み、一般的に次のように説明し、逆問題リストの
そのような逆のセットとして単一リンクリストの調整機能を達成するために、リストのヘッドノードの単一ヘッド所与のノード間のすべてのKを行う、およびグループのリストの最後から始まり、グループの先頭の残りのノードの十分でない数私たちは逆にする必要があります。(またはスタック補助キューとして使用することができません)
たとえば、次の
リスト:1-> 2-> 3-> 4- > 5-> 6> 7> 8>ヌル、K = 3。次いで6-> 7> 8,3-> 4-> 5,1> 2セット。調整:1-> 2-> 5-> 4- > 3-> 8> 7> 6>ヌル。請求項1はしないグループので、調整されません。
答え
この質問の難易度は、リストの末尾からではないのリストから、最初から設定されている、ということであるヘッドヘッドは、その後、我々はまだやることが比較的容易である場合は、リストを横切ることができるので、それぞれのトラバースにkは、逆にグループに分割されます。それは、一本鎖で戻って一緒にグループを横断することはできませんので、しかし、言葉の端から、同じではありません。しかし、この質問は非常に私の記事を参照して再帰を理解していない推奨する前に書かれた、再帰を行うに確かに優れているあなたは再帰を学ぶことができないのはなぜ?再帰さよなら、私の経験のいくつかについて話をし、記事では、再帰的なルーチンについてのいくつかを書きました。
第1の類似逆転タイトルを行います
問題を解決する前に、私たちは見て真似しないでくださいあなたはそれ以来、グループの先頭から開始した場合、私はそれを行うべきか、?たとえば、次のリスト:1-> 2-> 3-> 4- > 5-> 6> 7> 8>ヌル、K = 3。調整:3-> 2-> 1-> 6- > 5-> 4-> 7-> 8>ヌル。請求項7,8はない群から、調整されません。
あなたは一重リンクリストを逆にする方法がわからない場合は、この問題については、私が前に書いたものを見ることができますどのようにエレガントな逆単一のリスト
我々は、この問題を仮定すると、再帰的に実施することができる使用方法reverseKNode()(それぞれ単一のリストとの間のノードKから関数は、逆の順序でヘッドが OH基から開始);関数の逆()メソッドは、単一であります逆の順序でリスト。
次いで、K = 3以下の単一リンクリスト、用。
私たちは、フロントを分割してバックKのノードをノード:
一時点の残りのリストは、元の問題の下位問題であるといえます。我々はreverseKNode()メソッドは、リストに各ノードKの温度ポイントの間逆転する呼び出すことができます。次のように、ノード3のヘッド点は逆の順序で実行されている()メソッドを逆呼び出します。
ここでも、この再帰は非常に私が見て記事を読んで、提案した再帰的な事を理解できない場合
その後、我々はそれに二つの部分を接続する必要があります。次のように最終的な結果は以下の通りでした。
コードは以下の通りであります:
//k个为一组逆序
public ListNode reverseKGroup(ListNode head, int k) {
ListNode temp = head;
for (int i = 1; i < k && temp != null; i++) {
temp = temp.next;
}
//判断节点的数量是否能够凑成一组
if(temp == null)
return head;
ListNode t2 = temp.next;
temp.next = null;
//把当前的组进行逆序
ListNode newHead = reverseList(head);
//把之后的节点进行分组逆序
ListNode newTemp = reverseKGroup(t2, k);
// 把两部分连接起来
head.next = newTemp;
return newHead;
}
//逆序单链表
private static ListNode reverseList(ListNode head) {
if(head == null || head.next == null)
return head;
ListNode result = reverseList(head.next);
head.next.next = head;
head.next = null;
return result;
}
このトピックに戻ります
これら二つの質問は類似しており、グループの先頭、先頭から道路からこのグループから起動するだけでなく、最初の25個の質問をleetcodeするだけであると言うことができます。インタビューでは、多くの場合、それはなり、そのような道路バイトの鼓動のタイトルとして、変形尾はあなたがどのように突然の取得を知らないかもしれない、オンに設定し始めました。もちろん、一部の人々は、突然、彼のスパイクを反映することができます。
其实这道题很好做滴,你只需要先把单链表进行一次逆序,逆序之后就能转化为从头部开始组起了,然后按照我上面的解法,处理完之后,把结果再次逆序即搞定。两次逆序相当于没逆序。
例如对于链表(其中 K = 3)
我们把它从尾部开始组起,每 K 个节点为一组进行逆序。步骤如下
1、先进行逆序
逆序之后就可以把问题转化为从头部开始组起,每 K 个节点为一组进行逆序。
2、处理后的结果如下
3、接着在把结果逆序一次,结果如下
代码如下
public ListNode solve(ListNode head, int k) {
// 调用逆序函数
head = reverse(head);
// 调用每 k 个为一组的逆序函数(从头部开始组起)
head = reverseKGroup(head, k);
// 在逆序一次
head = reverse(head);
return head;
}
类似于这种需要先进行逆序的还要两个链表相加,这道题字节跳动的笔试题也有出过,如下图的第二题
这道题就需要先把两个链表逆序,再节点间相加,最后在合并了。
总结
关于链表的算法题,在面试的时候听说是挺常考的,大家可以多注意注意,遇到不错的链表算法题,也欢迎扔给我勒。
如果你觉得这篇内容对你挺有启发,为了让更多的人看到这篇文章:不妨
1、点赞,让更多的人也能看到这篇内容(收藏不点赞,都是耍流氓 -_-)
2、关注我和专栏,让我们成为长期关系
3、关注公众号「苦逼的码农」,主要写算法、计算机基础之类的文章,里面已有100多篇原创文章
大部分的数据结构与算法文章被各种公众号转载相信一定能让你有所收获
我也分享了很多视频、书籍的资源,以及开发工具,欢迎各位的关注我的公众号:苦逼的码农,第一时间阅读我的文章。