ヘッドに尾からのリストを印刷1.
リストを入力し、リストには、ArrayListののヘッドエンドから順に返さ
私の解決策
この質問は、非常に単純で、リストには添字配列要素は、配列のメソッドを介して、最初から取るべき横断要素にのみ、リスト、配列にアンシフトスクラッチ追加要素を有することができない、このようなシーケンスは、ヘッドに尾からです。
function printListFromTailToHead(head)
{
var array=[]
var current=head
while(current){
array.unshift(current.val)
current = current.next
}
return array
}
2.リンクリストリングの入口ノード
私の解決策
もちろん、リングがある場合は、その後、そのノードが追加プロパティを持つことになり、ノードを横断する前に、接続点があるだろう、ノードに属性を追加し、ノードを横断最初から最後まで、間違っています。しかし、そうするために、それは元のデータを破壊しました
その他の分析
1. 2個セットのポインタは、高速と低速、高速のポインタのポインタが二倍遅い速度です。リングが存在する場合、どちらも、リングノードで満たします。
2.次に、開始ノードへのヘッドポインタ、出会いから始まる他のノードが、等速、両方のノードがリング入口再び満たされます
証明します
ゆっくりとリングに、物理的な問題を追いかけているポインタが、2は確かに満たされるとき1.ポインタが速く、それぞれ、二つのステップ、ステップごとに遅い遅いポインタを取ります。
2.上記のように、ACの長さは、CBの長さb、BCの長さcを仮定しました。ときに会いました:
-
それは+ kを(B + C)+ Bに迅速にポインタを移動し、K> = 1
-
遅いポインタが+ bに旅しました。
式にちょうど2つのポイントがあります。
- K> = 1である定数、高速ループは、約、追いつくために遅かった失敗した場合、2つの異なる速度に反して、経過時間、同じ距離の両方
- 確かに遅い旋回は、リングの周りに遅い場合、速い確かに周りの二つのリングはすでに満たされていません
したがって、2(+のB)= A + K(B + C)+ B、K> = 1、それによりA =(K-1)(B + C)+ C、K> = 1。意味表現は:ミーティングポイントまでの距離リングリストヘッドは、入口リング+(K-1)リングの長さへの入口までの距離を=。二つのポインタ同じ満たす点Aポインタから開始時間と同じ長さで同じ距離を介して速度、及び環入口にリングの周りにCポインタから出発点。
function EntryNodeOfLoop(pHead){
var fast = pHead
var slow = pHead
while(fast!=null&&fast.next!=null){
slow = slow.next
fast = fast.next.next
if(slow == fast){
let p = pHead
while(p!=slow){
p = p.next
slow = slow.next
}
return p
}
}
return null
}
サプリメント
ループの長さ:環におけるB点は、新たな記録位置変数、この点からポインタ、一方は、カウント決意点と現在のレコード、カウントがループ長である点にレコードバック歩きました。
リストの長さ:ループ長が既知であるが、の値を加えたリストの長さです。
重複したノードリストを削除する3。
ソートされたリンクリストが重複ノードリストを削除し、重複ノードにおいて、ノードは、繰り返しを保持しない、ヘッド・ポインタ・リストを返します。例えば、リスト1-> 2-> 3-> 3-> 4-> 4-> 5扱われ1-> 2-> 5
私の解決策
とんでもない、だけでなく、リストの構造の理解を深め、そのようなリストを削除する方法としての間違った(私はこの質問それ日を探していたと思っただろう誰)
その他の分析
1.どのノードリンクリストを削除するには?次のポインタの前のノードによってポインタの変更があります。
- あなたがしたいこの質問は、ノードを削除するので、必ず現在のノードのCUR前中間変数ノードを記録するために、ここで事前に設定し、。
- また、それは、その後、最初のノードがどのように削除するように繰り返され、第1ノードと第2ノードの特殊なケースと考えられていますか?これは、接合ああ前ではありません!だから、あなたはヘッドノードを設定する、最初のノードを削除するために私たちを助けます
2.preポインタアクション:それは、現在のノードの前のノードで、重複したポイントに節点をスキップするポインタを変更するには、繰り返されることはありません。それは、それをノードの前にありましたか?ただ、我々は時間の次のポイント、ライン上の点への事前のポインタに繰り返しトラバースしないときにすることを、現在決定したポイントを繰り返さないでください。
/*function ListNode(x){
this.val = x;
this.next = null;
}*/
function deleteDuplication(pHead)
{
var Head = new ListNode(0) //设置一个头结点
Head.next = pHead //指向第一个结点
var pre = Head
var cur = pHead
while(cur != null){
if(cur.next!=null&&cur.val == cur.next.val){
while(cur.next!=null&&cur.val == cur.next.val){
cur = cur.next
}
pre.next = cur.next
cur = cur.next
}else{
pre = pre.next
cur = cur.next
}
}
return Head.next
}
3.クロスボーダー処理の問題は
私が最初に最も外側のループは、次のノードが現在のノードの説明は、外ループの最後のノードであり、空であるか否かを判断直接に、以下のサイクリング条件を書きました。リストには、これは権利ではないので、それはエラーになります空の場合しかし、それはでした。
while(cur.next != null){
if(cur.val == cur.next.val){
while(cur.val == cur.next.val){
4.preアップデート:私は愚かな、おそらく、長い時間のためだと思います。
彼らは次の重複ノードを見つけた場合、我々はノードを検索し、実行する最後のものは削除される繰り返し!したがって、事前の次のポインタを変更します
pre.next = cur.next
次のノードと現在のノードが同じではない見つけたとき、PREはフロント位置連で最新のポイントに更新されない(ノード位置にリピートポイントにないと判断された)であります
pre = pre.next
4.複製複雑なリスト
複合入力リスト(各ノードは、ノードの値を有し、二つのポインタ、次のノードへの1つのポインティング、他のノードへの特別なポインタ)は、複雑なリストの複製の頭部後の値を返します。(出力結果は、パラメータノード参照を返さないことに注意、それ以外のプログラムは、直接、空の宣告質問に戻ります)
私の解決策
どのようにすることができますIソリューション
その他の分析
スリーステップの
方式は、安全性が非常に直感的な与えられたことを証明マップ、明確な思考を描画するために、コードを書くことは実際には非常に良いです
function Clone(pHead)
{
if(pHead == null) return null
let pNode = pHead
//第一步:复制每个结点,把新结点插入旧结点的后面
while(pNode){
let cloneNode = new RandomListNode(pNode.label)
cloneNode.next = pNode.next //注意赋值顺序
pNode.next = cloneNode
pNode = cloneNode.next
}
//第二步:旧结点的random复制
pNode = pHead
while(pNode){
if(pNode.random){ //这个判断要有
pNode.next.random = pNode.random.next
}
pNode = pNode.next.next
}
//第三步:拆分链表
pNode = pHead
let cloneHead = pHead.next
let cloneNode = cloneHead
while(pNode){
pNode.next = pNode.next.next
if(cloneNode.next){
cloneNode.next = cloneNode.next.next
}
pNode = pNode.next
cloneNode = cloneNode.next
}
return cloneHead
}
ハッシュは、
古いものと新しいノード間の関係をマッピングするハッシュテーブルで表されます。キーは、古いノードで、値が新しいノードです。ここでは、新しいデータ構造ES6マップを使用する必要があります。特別なオブジェクトを、それが重要なターゲットになることができます。
- 最初のパス:コピー古いポインタ値と次のノード、古いものと新しいノードとの間のマップ格納されているマッピング関係を有します
- 第二のパス:旧マップを介してノードに対応する新しいノードを取得するには、新しいポインタは、ランダムなノードを更新しています
function Clone(pHead)
{
if(pHead == null) return null
let map = new Map()
let pNode = pHead
//新链表的头
let cloneHead = new RandomListNode(pHead.label)
let cloneNode = cloneHead
map.set(pNode,cloneNode) //先把两个头放进去,代码会简洁一点
//第一次遍历:复制旧结点的值和next
while(pNode){
//创建新结点
if(pNode.next){ //这个判断一定要有
cloneNode.next = new RandomListNode(pNode.next.label)
}else{
cloneNode.next = null
}
cloneNode = cloneNode.next
pNode = pNode.next
map.set(pNode,cloneNode) //结点对存入map中
}
//第二次遍历:复制random指针
pNode = pHead
while(pNode){
if(pNode.random){
//map的get方法:由键取值
map.get(pNode).random = map.get(pNode.random)
}
pNode = pNode.next
}
return cloneHead
}
二分探索木と二重リンクリスト
バイナリ検索ツリーを入力し、二重リンクリストに変換し、バイナリ検索ツリーは、ソートされました。要件は、ツリーのノードポインタを調整するために、ポイントを任意の新しいノードを作成することはできません。
私の解決策
結果は、使用前順を示してソートするには、それが大にわずかです。同時に作成されたノードを横断し、ポインタを変更します。私は本当にしないように、
その他の分析
これは、最も左の部分木と右部分木の最大接続点の要約を記録する必要がある以下の分析を、勝ちます。このようなルートやリンク、木全体が良く変換されます。
本明細書で事前へのポインタを記録します。
再帰
- 変換機能クリア機能。
入力:バイナリ検索ツリーのルートノードを入力します。
プロセス:注文した二重にリンクされたリストに変換します。
出力:リンクリストのヘッドノードを返します。 - クリア最後のメンバ変数関数。
現在のノードリストの最後の最後を記録します。 - 再帰的な手続きをクリアします。
再帰プロセスは、多くの木にツリー全体の分解をトラバースするために従うことと等価である、と彼らは短い、短い二重リンクリストに形質転換しました。リストの合計リサイクルの記録の終了を過ぎて、これらの小片のリストは、別の後、エンドいずれかに添加しました。
再帰的なコードは、私のコードの先頭で、本当に頭痛でこれです
function Convert(pRootOfTree)
{
if(pRootOfTree == null) return null
let last = null
ConvertCore(pRootOfTree,last)
let pHead = pRootOfTree
while(pHead.left){
pHead = pHead.left
}
return pHead
}
function ConvertCore(root,last){
if(root == null) return
ConvertCore(root.left,last)
root.left = last
if(last) last.right = root
last = root
ConvertCore(root.right,last)
}
与えられた
以下のようなツリー構造を見ることができる4,6,8,12の4つのノードはなかったです。
通常、私の推測では、問題の最後の更新でに、次のコードをエラーの原因を見つけることができませんでした。
function Convert(pRootOfTree)
{
if(pRootOfTree == null) return null
let last = null
ConvertCore(pRootOfTree,last)
let pHead = pRootOfTree
while(pHead.left){
pHead = pHead.left
}
return pHead
}
function ConvertCore(root,last){
if(root == null) return
if(root.left){
last = ConvertCore(root.left,last)
}
root.left = last
if(last) last.right = root
last = root
if(root.right){
last = ConvertCore(root.right,last)
}
return last
}
非再帰
同時再帰的配列、現在のリンクリストのノードの最後にプリレコードポインタのポイントを必要とします。本当に良く再帰よりも多くのことを理解しています。
function Convert(pRootOfTree)
{
if (pRootOfTree == null) return null
let stack = [];
let node = pRootOfTree
let pre = null
let head = null
while (stack.length || node) {
//一直遍历到树的最左边也就是最小值
if (node) {
stack.push(node);
node = node.left;
} else {
//最左子结点出栈
let top = stack.pop()
//pre为null说明top就是最左子结点就是链表的头
if (pre == null) {
head = top
} else { //pre不为null,那就需要top的左右指针赋值
pre.right = top
}
top.left = pre
pre = top //链表最后结点就是top了
node = top.right
}
}
return head
}
6.二つのリストの共通ノード
二つの入力リスト、その第1の共通のノードを見つけます。(試験データの誤りが受信データが正しいことを確認するために他の方法で表示されるように、入ってくるデータは、リンクされたリストであるため、ことに留意されたいです)
私の解決策
ダブルポインタは、ポインタは同じ、短鎖は、次の、2つのポインタのポインタを歩き始めた同じことが必要であるか否かを判断する来る短いリストの残りの長さのように、長鎖を行きます。
明らかに、二つのリストの長さを取得します。
function FindFirstCommonNode(pHead1, pHead2)
{
if(pHead1 == null||pHead2 == null)
return null
let gap = GetListLength(pHead1)- GetListLength(pHead2)
let short = pHead1,long = pHead2
//要知道哪个是长链表
if(gap>0){
short = pHead2
long = pHead1
}
//long先走
while(gap--){
long = long.next
}
//开始一起走
while(long!=null){
if(long==short){
return long
}
long = long.next
short = short.next
}
}
//获取链表长
function GetListLength(pHead){
let cur = pHead
let len = 0
while(cur){
len++
cur = cur.next
}
return len
}