Skip to content

Commit 300f49b

Browse files
author
legolas.zhan
committed
138. Copy List with Random Pointer && upgrade to go1.23
1 parent 0fcf81a commit 300f49b

File tree

4 files changed

+134
-2
lines changed

4 files changed

+134
-2
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ result
22
leetcode.db
33
.vscode/
44

5-
vendor/*
5+
vendor/*
6+
.DS_Store

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/TTWShell/algorithms
22

3-
go 1.19
3+
go 1.23
44

55
require github.com/stretchr/testify v1.7.0
66

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/* https://leetcode.com/problems/copy-list-with-random-pointer/?envType=study-plan-v2&envId=top-interview-150
2+
*/
3+
4+
package lll
5+
6+
type Node struct {
7+
Val int
8+
Next *Node
9+
Random *Node
10+
}
11+
12+
func copyRandomList(head *Node) *Node {
13+
if head == nil {
14+
return nil
15+
}
16+
17+
// Step 1: Insert copy nodes into original list
18+
cur := head
19+
for cur != nil {
20+
newNode := &Node{Val: cur.Val, Next: cur.Next}
21+
cur.Next = newNode
22+
cur = newNode.Next
23+
}
24+
25+
// Step 2: Assign random pointers for copied nodes
26+
cur = head
27+
for cur != nil {
28+
if cur.Random != nil {
29+
cur.Next.Random = cur.Random.Next
30+
}
31+
cur = cur.Next.Next
32+
}
33+
34+
// Step 3: Separate original and copied lists
35+
oldList := head
36+
newList := head.Next
37+
newHead := newList
38+
for oldList != nil {
39+
oldList.Next = oldList.Next.Next
40+
if newList.Next != nil {
41+
newList.Next = newList.Next.Next
42+
}
43+
oldList = oldList.Next
44+
newList = newList.Next
45+
}
46+
47+
return newHead
48+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package lll
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
)
8+
9+
func TestCopyRandomList(t *testing.T) {
10+
// Helper function to build linked list from input
11+
buildList := func(input [][]interface{}) *Node {
12+
if len(input) == 0 {
13+
return nil
14+
}
15+
nodes := make([]*Node, len(input))
16+
for i, val := range input {
17+
nodes[i] = &Node{Val: val[0].(int)}
18+
}
19+
for i, val := range input {
20+
if i < len(input)-1 {
21+
nodes[i].Next = nodes[i+1]
22+
}
23+
if val[1] != nil {
24+
nodes[i].Random = nodes[val[1].(int)]
25+
}
26+
}
27+
return nodes[0]
28+
}
29+
30+
// Helper function to convert list to [][]interface{} for comparison
31+
convertList := func(head *Node) [][]interface{} {
32+
var result [][]interface{}
33+
indexMap := make(map[*Node]int)
34+
cur := head
35+
index := 0
36+
for cur != nil {
37+
indexMap[cur] = index
38+
cur = cur.Next
39+
index++
40+
}
41+
cur = head
42+
for cur != nil {
43+
if cur.Random != nil {
44+
result = append(result, []interface{}{cur.Val, indexMap[cur.Random]})
45+
} else {
46+
result = append(result, []interface{}{cur.Val, nil})
47+
}
48+
49+
cur = cur.Next
50+
}
51+
return result
52+
}
53+
54+
tests := []struct {
55+
name string
56+
input [][]interface{}
57+
expected [][]interface{}
58+
}{
59+
{
60+
name: "Example 1",
61+
input: [][]interface{}{{7, nil}, {13, 0}, {11, 4}, {10, 2}, {1, 0}},
62+
expected: [][]interface{}{{7, nil}, {13, 0}, {11, 4}, {10, 2}, {1, 0}},
63+
},
64+
{
65+
name: "Example 2",
66+
input: [][]interface{}{{1, 1}, {2, 1}},
67+
expected: [][]interface{}{{1, 1}, {2, 1}},
68+
},
69+
{
70+
name: "Example 3",
71+
input: [][]interface{}{{3, nil}, {3, 0}, {3, nil}},
72+
expected: [][]interface{}{{3, nil}, {3, 0}, {3, nil}},
73+
},
74+
}
75+
76+
for _, tt := range tests {
77+
t.Run(tt.name, func(t *testing.T) {
78+
head := buildList(tt.input)
79+
copiedList := copyRandomList(head)
80+
assert.Equal(t, tt.expected, convertList(copiedList))
81+
})
82+
}
83+
}

0 commit comments

Comments
 (0)