diff --git a/83.-Remove-Duplicates-from-Sorted-List/memo.md b/83.-Remove-Duplicates-from-Sorted-List/memo.md new file mode 100644 index 0000000..5bcae1f --- /dev/null +++ b/83.-Remove-Duplicates-from-Sorted-List/memo.md @@ -0,0 +1,25 @@ +# step1 +考えたこと +- setで通った値を管理して重複していたら組み換える。でもaccendingだったら切り替わりだけ見れば十分か。組み替えると破壊的なのでちょっと微妙 +- 新しく単方向リストを作る。入力を順にたどって切り替わりでリストを伸ばす。 +- ポインタに慣れておらず、newをつけておらず合わない。 + + +# step2 +- アルゴリズムは本質的に同じだけど、新井さんの解答をリストに対して破壊的なのでどっちがよいかは状況によりそう。面接なら確認しながら確認する。 +- 変数名がnow, ans, ansNowがわかりにくいのでchatpgtに代替案を考えてもらった。それぞれcurrentNode, resultHead, resultTailを採用。 + +| 役割 | 変数名候補(20個) | +|----------------|------------------------------------------------------------------------------------| +| **now** | current, currNode, traverse, cursor, walker, scan, nodePtr, reader, iterator, scanPtr, listWalker, inputCursor, explorer, readHead, probe, listPtr, sourcePtr, originWalker, traversePtr, scanNode | +| **ans** | resultHead, outputHead, newListHead, headOfResult, dedupedHead, uniqueListHead, resultList, filteredHead, cleanedListHead, distinctHead, newHead, answerHead, finalList, resultStart, startNode, processedHead, rootNode, firstNode, topOfResult, primaryNode | +| **ansNow** | resultTail, lastNode, resPtr, builder, insertPos, resultCursor, tail, constructPtr, appendNode, writer, resBuilder, outPtr, resultWalker, resultCurrent, collector, newTail, sinkPtr, outputTail, outCursor, resultIterator | + +- whileとifが入り乱れてデバッグに時間がかかってしまった。次のように整理した. +今見ているノード(!= nullptr)を基準に次の3パターンがある。 +1. 次がnullptr +2. 次のノードが今見ているノードと値が異なる。 +3. 次のノードが今見ているノードと値が等しい。 + + +1,2のときは見るノードを次に進めればよく、3のときだけ次のノードを組み替える。組み替えた先のノードが妥当かは次のループで見る。 diff --git a/83.-Remove-Duplicates-from-Sorted-List/step1.cpp b/83.-Remove-Duplicates-from-Sorted-List/step1.cpp new file mode 100644 index 0000000..1faf8ed --- /dev/null +++ b/83.-Remove-Duplicates-from-Sorted-List/step1.cpp @@ -0,0 +1,30 @@ +// 戻り値用に新しくリストを作る方針 + +struct ListNode { + int val; + ListNode* next; + ListNode() : val(0), next(nullptr) {} + ListNode(int x) : val(x), next(nullptr) {} + ListNode(int x, ListNode* next) : val(x), next(next) {} +}; + +class Solution { + public: + ListNode* deleteDuplicates(ListNode* head) { + if (head == nullptr) { + return nullptr; + } + ListNode* now = head; + ListNode* ans = new ListNode(head->val); + ListNode* ansNow = ans; + while (now != nullptr && now->next != nullptr) { + if (now->val != now->next->val) { + ListNode* append = new ListNode(now->next->val); + ansNow->next = append; + ansNow = ansNow->next; + } + now = now->next; + } + return ans; + } +}; diff --git a/83.-Remove-Duplicates-from-Sorted-List/step2.cpp b/83.-Remove-Duplicates-from-Sorted-List/step2.cpp new file mode 100644 index 0000000..7897cf3 --- /dev/null +++ b/83.-Remove-Duplicates-from-Sorted-List/step2.cpp @@ -0,0 +1,31 @@ +// 戻り値用に新しくリストを作る解答 + +struct ListNode { + int val; + ListNode* next; + ListNode() : val(0), next(nullptr) {} + ListNode(int x) : val(x), next(nullptr) {} + ListNode(int x, ListNode* next) : val(x), next(next) {} +}; + +class Solution { + ListNode* deleteDuplicates(ListNode* head) { + if (head == nullptr) { + return nullptr; + } + ListNode* currentNode = head; + ListNode* resultHead = new ListNode(head->val); + ListNode* resultTail = resultHead; + while (currentNode != nullptr && currentNode->next != nullptr) { + if (currentNode->next != nullptr && currentNode->val == currentNode->next->val) { + currentNode->next = currentNode->next->next; + } else { + ListNode* append = new ListNode(currentNode->next->val); + currentNode = currentNode->next; + resultTail->next = append; + resultTail = resultTail->next; + } + } + return resultHead; + } +}; diff --git a/83.-Remove-Duplicates-from-Sorted-List/step2_another.cpp b/83.-Remove-Duplicates-from-Sorted-List/step2_another.cpp new file mode 100644 index 0000000..4b3b7c7 --- /dev/null +++ b/83.-Remove-Duplicates-from-Sorted-List/step2_another.cpp @@ -0,0 +1,25 @@ +// 入力のリストを直接改変する方法 + +struct ListNode { + int val; + ListNode* next; + ListNode() : val(0), next(nullptr) {} + ListNode(int x) : val(x), next(nullptr) {} + ListNode(int x, ListNode* next) : val(x), next(next) {} +}; + +class Soltion { + public: + ListNode* deleteDuplicates(ListNode* head) { + ListNode* currentNode = head; + while (currentNode != nullptr) { + // 次のノードの値が条件を満たさない場合、その次のノードにつなげる。 + if (currentNode->next != nullptr && currentNode->val != currentNode->next->val) { + currentNode->next = currentNode->next->next; + } else { + currentNode = currentNode->next; + } + } + return head; + } +}; diff --git a/83.-Remove-Duplicates-from-Sorted-List/step3.cpp b/83.-Remove-Duplicates-from-Sorted-List/step3.cpp new file mode 100644 index 0000000..1c058f1 --- /dev/null +++ b/83.-Remove-Duplicates-from-Sorted-List/step3.cpp @@ -0,0 +1,26 @@ +// 入力のリストを改変する解法 + +struct ListNode { + int val; + ListNode* next; + ListNode() : val(0), next(nullptr) {} + ListNode(int x) : val(x), next(nullptr) {} + ListNode(int x, ListNode* next) : val(x), next(next) {} +}; + +class Solution { + public: + ListNode* deleteDuplicates(ListNode* head) { + ListNode* tail = head; + while (tail != nullptr) { + if (tail->next == nullptr || tail->val != tail->next->val) { + tail = tail->next; + } else { + ListNode* toDelete = tail->next; + tail->next = tail->next->next; + delete toDelete; + } + } + return head; + } +}; diff --git a/83.-Remove-Duplicates-from-Sorted-List/step3_another.cpp b/83.-Remove-Duplicates-from-Sorted-List/step3_another.cpp new file mode 100644 index 0000000..ca01ccb --- /dev/null +++ b/83.-Remove-Duplicates-from-Sorted-List/step3_another.cpp @@ -0,0 +1,30 @@ +struct ListNode { + int val; + ListNode* next; + ListNode() : val(0), next(nullptr) {} + ListNode(int x) : val(x), next(nullptr) {} + ListNode(int x, ListNode* next) : val(x), next(next) {} +}; + +class Solution { + public: + // 入力のリストも戻り値のリストもメモリ管理は呼び出し元で行う必要がある。 + ListNode* deleteDuplicates(ListNode* head) { + ListNode* nowNode = head; + ListNode* resultHead = nowNode ? new ListNode(nowNode->val) : nullptr; + ListNode* resultTail = resultHead; + while (nowNode != nullptr) { + if (nowNode->next == nullptr) { + break; + // 次のノードの値が異なる値であれば戻り値のリストに追加する + } else if (nowNode->val != nowNode->next->val) { + ListNode* appendNode = new ListNode(nowNode->next->val); + resultTail->next = appendNode; + resultTail = resultTail->next; + } + // 次のノードも同じ値の場合は何も追加せずに進んでよい + nowNode = nowNode->next; + } + return resultHead; + } +};