Skip to content

Commit 9bdba50

Browse files
committed
Find pivot index + Remove duplicates from sorted array II
1 parent 62ae40f commit 9bdba50

File tree

4 files changed

+373
-0
lines changed

4 files changed

+373
-0
lines changed

724.find_pivot_index/find_pivot.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// 724. Find pivot index
2+
// Topics: 'Array', 'Prefix Sum'
3+
4+
// Given an array of integers nums, calculate the pivot index of this array.
5+
6+
// The pivot index is the index where the sum of all the numbers strictly to the left of the index is equal to the sum of all the numbers strictly to the index's right.
7+
8+
// If the index is on the left edge of the array, then the left sum is 0 because there are no elements to the left. This also applies to the right edge of the array.
9+
10+
// Return the leftmost pivot index. If no such index exists, return -1.
11+
12+
// Example 1:
13+
14+
// Input: nums = [1,7,3,6,5,6]
15+
// Output: 3
16+
// Explanation:
17+
// The pivot index is 3.
18+
// Left sum = nums[0] + nums[1] + nums[2] = 1 + 7 + 3 = 11
19+
// Right sum = nums[4] + nums[5] = 5 + 6 = 11
20+
21+
// Example 2:
22+
23+
// Input: nums = [1,2,3]
24+
// Output: -1
25+
// Explanation:
26+
// There is no index that satisfies the conditions in the problem statement.
27+
28+
// Example 3:
29+
30+
// Input: nums = [2,1,-1]
31+
// Output: 0
32+
// Explanation:
33+
// The pivot index is 0.
34+
// Left sum = 0 (no elements to the left of index 0)
35+
// Right sum = nums[1] + nums[2] = 1 + -1 = 0
36+
37+
// Constraints:
38+
39+
// 1 <= nums.length <= 104
40+
// -1000 <= nums[i] <= 1000
41+
42+
package findpivotindex
43+
44+
func pivotIndex(nums []int) int {
45+
if len(nums) <= 1 {
46+
return 0
47+
}
48+
var suffix int
49+
for i := len(nums) - 1; i > 0; i-- {
50+
suffix += nums[i]
51+
}
52+
53+
var prefix int
54+
for i := 0; i < len(nums); i++ {
55+
if prefix == suffix {
56+
return i
57+
}
58+
if i < len(nums)-1 {
59+
suffix -= nums[i+1]
60+
}
61+
prefix += nums[i]
62+
}
63+
if prefix == suffix {
64+
return len(nums) - 1
65+
}
66+
return -1
67+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package findpivotindex
2+
3+
import "testing"
4+
5+
func TestPivotIndex(t *testing.T) {
6+
tests := []struct {
7+
name string
8+
nums []int
9+
expected int
10+
}{
11+
{
12+
name: "example 1 - pivot in middle",
13+
nums: []int{1, 7, 3, 6, 5, 6},
14+
expected: 3,
15+
},
16+
{
17+
name: "example 2 - no pivot exists",
18+
nums: []int{1, 2, 3},
19+
expected: -1,
20+
},
21+
{
22+
name: "example 3 - pivot at start",
23+
nums: []int{2, 1, -1},
24+
expected: 0,
25+
},
26+
{
27+
name: "single element",
28+
nums: []int{1},
29+
expected: 0,
30+
},
31+
{
32+
name: "two elements - no pivot",
33+
nums: []int{1, 2},
34+
expected: -1,
35+
},
36+
{
37+
name: "two elements - pivot at start",
38+
nums: []int{0, 0},
39+
expected: 0,
40+
},
41+
{
42+
name: "all zeros",
43+
nums: []int{0, 0, 0, 0},
44+
expected: 0,
45+
},
46+
{
47+
name: "pivot at end",
48+
nums: []int{-1, -1, 0, 1, 1, 0},
49+
expected: 5,
50+
},
51+
{
52+
name: "negative numbers - pivot exists",
53+
nums: []int{-1, -1, -1, 0, 1, 1},
54+
expected: 0,
55+
},
56+
{
57+
name: "mixed positive and negative",
58+
nums: []int{1, -1, 2, -1, 1},
59+
expected: 2,
60+
},
61+
{
62+
name: "large positive sum on left",
63+
nums: []int{100, -99, -1, 0},
64+
expected: 3,
65+
},
66+
{
67+
name: "leftmost pivot when multiple exist",
68+
nums: []int{0, 0, 0},
69+
expected: 0,
70+
},
71+
{
72+
name: "larger array no pivot",
73+
nums: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
74+
expected: -1,
75+
},
76+
{
77+
name: "array with zero in middle as pivot",
78+
nums: []int{5, 5, 0, 5, 5},
79+
expected: 2,
80+
},
81+
}
82+
83+
for _, tt := range tests {
84+
t.Run(tt.name, func(t *testing.T) {
85+
result := pivotIndex(tt.nums)
86+
if result != tt.expected {
87+
t.Errorf("pivotIndex(%v) = %d; expected %d", tt.nums, result, tt.expected)
88+
}
89+
})
90+
}
91+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// 80. Remove duplicates from sorted array II
2+
// Topics: 'Array', 'Two Pointers'
3+
// Level: 'Medium'
4+
5+
// Given an integer array nums sorted in non-decreasing order, remove some duplicates in-place such that each unique element appears at most twice. The relative order of the elements should be kept the same.
6+
7+
// Since it is impossible to change the length of the array in some languages, you must instead have the result be placed in the first part of the array nums. More formally, if there are k elements after removing the duplicates, then the first k elements of nums should hold the final result. It does not matter what you leave beyond the first k elements.
8+
9+
// Return k after placing the final result in the first k slots of nums.
10+
11+
// Do not allocate extra space for another array. You must do this by modifying the input array in-place with O(1) extra memory.
12+
13+
// Custom Judge:
14+
15+
// The judge will test your solution with the following code:
16+
17+
// int[] nums = [...]; // Input array
18+
// int[] expectedNums = [...]; // The expected answer with correct length
19+
20+
// int k = removeDuplicates(nums); // Calls your implementation
21+
22+
// assert k == expectedNums.length;
23+
// for (int i = 0; i < k; i++) {
24+
// assert nums[i] == expectedNums[i];
25+
// }
26+
27+
// If all assertions pass, then your solution will be accepted.
28+
29+
// Example 1:
30+
31+
// Input: nums = [1,1,1,2,2,3]
32+
// Output: 5, nums = [1,1,2,2,3,_]
33+
// Explanation: Your function should return k = 5, with the first five elements of nums being 1, 1, 2, 2 and 3 respectively.
34+
// It does not matter what you leave beyond the returned k (hence they are underscores).
35+
36+
// Example 2:
37+
38+
// Input: nums = [0,0,1,1,1,1,2,3,3]
39+
// Output: 7, nums = [0,0,1,1,2,3,3,_,_]
40+
// Explanation: Your function should return k = 7, with the first seven elements of nums being 0, 0, 1, 1, 2, 3 and 3 respectively.
41+
// It does not matter what you leave beyond the returned k (hence they are underscores).
42+
43+
// Constraints:
44+
45+
// 1 <= nums.length <= 3 * 104
46+
// -104 <= nums[i] <= 104
47+
// nums is sorted in non-decreasing order.
48+
49+
package removeduplicatesfromsortedarrayii
50+
51+
func removeDuplicates(nums []int) int {
52+
m := map[int]int{nums[0]: 1}
53+
var i int
54+
for j := 1; j < len(nums); j++ {
55+
count := m[nums[j]]
56+
if count < 2 || nums[i] != nums[j] {
57+
i++
58+
nums[i] = nums[j]
59+
}
60+
m[nums[j]]++
61+
}
62+
return i + 1
63+
}
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
package removeduplicatesfromsortedarrayii
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestRemoveDuplicates(t *testing.T) {
8+
tests := []struct {
9+
name string
10+
nums []int
11+
expected int
12+
result []int
13+
}{
14+
{
15+
name: "Example 1",
16+
nums: []int{1, 1, 1, 2, 2, 3},
17+
expected: 5,
18+
result: []int{1, 1, 2, 2, 3},
19+
},
20+
{
21+
name: "Example 2",
22+
nums: []int{0, 0, 1, 1, 1, 1, 2, 3, 3},
23+
expected: 7,
24+
result: []int{0, 0, 1, 1, 2, 3, 3},
25+
},
26+
{
27+
name: "Single element",
28+
nums: []int{1},
29+
expected: 1,
30+
result: []int{1},
31+
},
32+
{
33+
name: "Two identical elements",
34+
nums: []int{1, 1},
35+
expected: 2,
36+
result: []int{1, 1},
37+
},
38+
{
39+
name: "Three identical elements",
40+
nums: []int{1, 1, 1},
41+
expected: 2,
42+
result: []int{1, 1},
43+
},
44+
{
45+
name: "All different elements",
46+
nums: []int{1, 2, 3, 4, 5},
47+
expected: 5,
48+
result: []int{1, 2, 3, 4, 5},
49+
},
50+
{
51+
name: "All same elements",
52+
nums: []int{2, 2, 2, 2, 2, 2},
53+
expected: 2,
54+
result: []int{2, 2},
55+
},
56+
{
57+
name: "Pairs only",
58+
nums: []int{1, 1, 2, 2, 3, 3},
59+
expected: 6,
60+
result: []int{1, 1, 2, 2, 3, 3},
61+
},
62+
{
63+
name: "Multiple groups with different counts",
64+
nums: []int{1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3},
65+
expected: 6,
66+
result: []int{1, 1, 2, 2, 3, 3},
67+
},
68+
{
69+
name: "Negative numbers",
70+
nums: []int{-5, -5, -5, -3, -3, -1},
71+
expected: 5,
72+
result: []int{-5, -5, -3, -3, -1},
73+
},
74+
{
75+
name: "Mix of negative and positive",
76+
nums: []int{-2, -2, -1, -1, -1, 0, 0, 1, 1, 1},
77+
expected: 8,
78+
result: []int{-2, -2, -1, -1, 0, 0, 1, 1},
79+
},
80+
{
81+
name: "Two elements different",
82+
nums: []int{1, 2},
83+
expected: 2,
84+
result: []int{1, 2},
85+
},
86+
{
87+
name: "Large numbers",
88+
nums: []int{10000, 10000, 10000, 10001, 10001},
89+
expected: 4,
90+
result: []int{10000, 10000, 10001, 10001},
91+
},
92+
{
93+
name: "Starting with many duplicates",
94+
nums: []int{1, 1, 1, 1, 1, 1, 1, 2, 3},
95+
expected: 4,
96+
result: []int{1, 1, 2, 3},
97+
},
98+
{
99+
name: "Ending with many duplicates",
100+
nums: []int{1, 2, 3, 3, 3, 3, 3, 3, 3},
101+
expected: 4,
102+
result: []int{1, 2, 3, 3},
103+
},
104+
}
105+
106+
for _, tt := range tests {
107+
t.Run(tt.name, func(t *testing.T) {
108+
// Make a copy for error messages
109+
original := make([]int, len(tt.nums))
110+
copy(original, tt.nums)
111+
112+
k := removeDuplicates(tt.nums)
113+
114+
if k != tt.expected {
115+
t.Errorf("removeDuplicates(%v) returned k = %d, expected %d", original, k, tt.expected)
116+
}
117+
118+
// Verify the first k elements match the expected result
119+
for i := 0; i < k; i++ {
120+
if tt.nums[i] != tt.result[i] {
121+
t.Errorf("removeDuplicates(%v) at index %d: got %d, expected %d", original, i, tt.nums[i], tt.result[i])
122+
}
123+
}
124+
})
125+
}
126+
}
127+
128+
func TestRemoveDuplicatesProperties(t *testing.T) {
129+
t.Run("Result is sorted", func(t *testing.T) {
130+
nums := []int{1, 1, 1, 2, 2, 3, 3, 3, 3}
131+
k := removeDuplicates(nums)
132+
133+
for i := 1; i < k; i++ {
134+
if nums[i] < nums[i-1] {
135+
t.Errorf("Result is not sorted: nums[%d]=%d < nums[%d]=%d", i, nums[i], i-1, nums[i-1])
136+
}
137+
}
138+
})
139+
140+
t.Run("No element appears more than twice", func(t *testing.T) {
141+
nums := []int{1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3}
142+
k := removeDuplicates(nums)
143+
144+
counts := make(map[int]int)
145+
for i := 0; i < k; i++ {
146+
counts[nums[i]]++
147+
if counts[nums[i]] > 2 {
148+
t.Errorf("Element %d appears more than twice in result", nums[i])
149+
}
150+
}
151+
})
152+
}

0 commit comments

Comments
 (0)