Task scheduling algorithm - algorithm

How do I go about the following problem? I have a sense to use DP
Given an array of the complexity of task, Note that the complexity is also the order of the task they need to be executed. The constraint is to have at least one task scheduled every day. The complexity of that day is the highest task complexity of that day. What is the overall minimum complexity that can be achieved with optimal planning?
For example, let's say there are n = 5 tasks, where:
complexity = [1, 5, 3, 2, 4]
and the length of the test is days = 2. The best option is to execute the first task on the first day and the rest on the second day. The complexity of the first day would be 1, since that's the only task, and the complexity of the second day would be 5, because that's the complexity level of the most complex task that day. Therefore, the answer is 1 + 5 = 6.
Example 1:
5 -> complexity[] size n = 5
30
10
40
20
50
2 -> Days =2
Output:
80

I think this is O(n2), so not super optimal, but it works. It's written in Go.
package main
import "fmt"
func optimize(tasks []int, days int) int {
// edge case 1: empty c or days <= 0
// (this is really for data input validation)
if len(tasks) == 0 || days <= 0 {
return 0
}
// edge case 2: single day - return max
if days == 1 {
max := tasks[0]
for _, v := range tasks[1:] {
if v > max {
max = v
}
}
return max
}
// edge case 3: tasks = days
if days == len(tasks) {
total := 0
for _, v := range tasks {
total += v
}
return total
}
// all other cases:
possibilities := []int{}
i := 0
max := tasks[0]
for {
tasksLeft := len(tasks[i+1:])
daysLeft := days - 1
if tasksLeft < daysLeft {
break
}
if tasks[i] > max {
max = tasks[i]
}
possibility := max + optimize(tasks[i+1:], days-1)
possibilities = append(possibilities, possibility)
i++
}
// minimize
min := possibilities[0]
for _, p := range possibilities[1:] {
if p < min {
min = p
}
}
return min
}
func main() {
tasks := []int{1, 5, 3, 2, 4}
days := 2
fmt.Println(optimize(tasks, days))
}

Related

How to solve problems Mark and Toys question on Hackerrank

I have tried solving the question, but some test cases failed.
The Question is: Mark and Jane are very happy after having their first
child. Their son loves toys, so Mark wants to buy some. There are a
number of different toys lying in front of him, tagged with their
prices. Mark has only a certain amount to spend, and he wants to
maximize the number of toys he buys with this money. Given a list of
toy prices and an amount to spend, determine the maximum number of
gifts he can buy.
Note Each toy can be purchased only once. Example prices = [1,2,3,4] k
= 7
The budget is 7 units of currency. He can buy items that cost [1, 2,
3] for 6, or [3, 4] for 7 units. The maximum is 3 items.
Function Description
Complete the function maximumToys in the editor below.
maximumToys has the following parameter(s):
int prices[n]: the toy prices
int k: Mark's budget
Returns
int: the maximum number of toys
The first line contains two integers, n and k, the number of priced
toys and the amount Mark has to spend. The next line contains n
space-separated integers prices[i]
sample input: 7 50 1 12 5 111 200 1000 10
sample output: 4
This is my answer:
func maximumToys(prices []int32, k int32) int32 {
// Write your code here
// Sorting the prices
for i := 0; i < len(prices); i++ {
for j := i + 1; j < len(prices); j++ {
// Swap the number
if prices[i] > prices[j] {
temp := prices[i]
prices[i] = prices[j]
prices[j] = temp
}
}
}
for l := 0; l < len(prices); l++ {
k -= int32(prices[l])
if k < prices[l] {
return int32(l)
}
}
lengthPrices := len(prices)
return int32(lengthPrices)
}
I have tried sorting the array of numbers and then variable k reduce with each number in the array. In the end, I return the length of array prices
enter link description here question Mark and Toys
It feels like the simplest strategy to just to buy the cheapest toys:
package main
import (
"log"
"sort"
)
func maximumToys(prices []int32, k int32) int32 {
sort.Slice(prices, func(a, b int) bool {
return prices[a] < prices[b]
})
sum := int32(0)
for i := 0; i < len(prices); i++ {
sum += prices[i]
if sum > k {
return int32(i)
}
}
return int32(len(prices))
}
func main() {
tests := []struct {
prices []int32
money, want int32
}{
{[]int32{1, 2, 3, 4}, 7, 3},
{[]int32{1, 12, 5, 111, 200, 1000, 10}, 50, 4},
}
for i, t := range tests {
n := maximumToys(t.prices, t.money)
log.Print("test ", i, " result: got=", n, " wanted=", t.want, " passed=", n == t.want)
}
}
import (
....
"sort"
)
func maximumToys(prices []int32, k int32) int32 {
// Write your code here
sort.Slice(prices, func(i, j int) bool {
return prices[i] < prices[j]
})
var sum float64 = 0
var count int32 = 0
for _, v := range prices {
sum = sum + float64(v)
if sum <= float64(k) {
count++
}
}
return count
}
or this one is you want to break the loop once you reach the limit
func maximumToys(prices []int32, k int32) int32 {
// Write your code here
sort.Slice(prices, func(i, j int) bool {
return prices[i] < prices[j]
})
var sum float64 = 0
var count int32 = 0
for _, v := range prices {
sum = sum + float64(v)
if sum > float64(k) {
break
}
count++
}
return count
}

Find the minimum absolute value between 2 elements of an array with minimum complexity

My goal is to find the minimum absolute value between 2 elements of an array, in the example below the min absolute value is beetwen 1 and 4 and the result is 3
Here is my implementation of the solution:
input := [6]int{8,1,13,30,4,20}
minAbsVal := math.MaxFloat64
for i := 0; i < len(input); i++ {
for j := i+1; j < len(input); j++ {
if math.Abs(float64(input[i] - input[j])) < minAbsVal {
minAbsVal = math.Abs(float64(input[i] - input[j]))
}
}
}
fmt.Println("Result", minAbsVal)
You can find the implémetation here : https://play.golang.org/p/D2DGy7YcVSv
I want to know if there is a solution with less complexity ?
You algorithm is currently O(n^2).
When sorted, smallest absolute difference must be between 2 sequential elements.
You can sort integers in O(n log n), with quick sort, merge sort etc. , and after having it sorted, you could have a final step with O(n)
There might be a better implementation with dynamic programming, maybe a single sorting algorithm where you also find the smallest difference, however, this is what I thought
sortedArray = sorted(array) // implement a sorted function
n := sortedArray[len(sortedArray) - 1)]
minDif := 2^32 // chose a better initial value like infinity
for i := range n-1 {
if sortedArray[i+1] - sortedArray[i] < minDif{
minDif = sortedArray[i + 1] - sortedArray[i]
}
}
return minDif
You could also use a Heap, it sorts itself:
package main
import (
"container/heap"
"sort"
)
type slice struct { sort.IntSlice }
func (s slice) Pop() interface{} { return 0 }
func (s slice) Push(x interface{}) {}
func main() {
s := slice{
sort.IntSlice{8, 1, 13, 30, 4, 20},
}
heap.Init(s)
println("Result", s.IntSlice[0])
}
https://golang.org/pkg/container/heap

Bridge and Torch Problem for 'n' people with Go [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
Problem: Given an array of positive distinct integer denoting the crossing time of ‘n’ people. These ‘n’ people are standing at one side of bridge. Bridge can hold at max two people at a time. When two people cross the bridge, they must move at the slower person’s pace. Find the minimum total time in which all persons can cross the bridge.
I am not able to find the pattern as of how to scale this for 'n' people. But somehow I managed to find the case with 4 people. Can someone help me with this. I am new to Golang and I am stuck with this problem.
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"sort"
"gopkg.in/yaml.v2"
)
type conf struct {
Person []map[string]float32 `yaml:"person"`
}
func (c *conf) getConf() *conf {
filename := os.Args[1] // Taking file input
yamlFile, err := ioutil.ReadFile(filename) // Yaml parse
if err != nil {
log.Printf("yamlFile.Get err #%v ", err)
}
err = yaml.Unmarshal(yamlFile, c)
if err != nil {
log.Fatalf("Unmarshal: %v", err)
}
return c
}
func main() {
var c conf // Object of struct conf
c.getConf() // calling getConf function
// Sorting the current conf map
n := map[float32][]string{} // Map to store current conf map
var a []float32 // Store values from conf map
for k, v := range c.Person {
v := float32(v)
fmt.Println(k, v)
n[v] = append(n[v], k)
}
for k := range n {
a = append(a, k)
}
// Converting float32 as float64 in order to sort the values in conf map
float32AsFloat64Values := make([]float64, len(a))
for i, val := range a {
float32AsFloat64Values[i] = float64(val)
}
sort.Float64s(float32AsFloat64Values)
for i, val := range float32AsFloat64Values {
a[i] = float32(val)
}
var time float32
fmt.Printf("\n%v\n", a)
for _, k := range a {
min1 := a[0]
min2 := a[1]
min3 := a[2]
for _, s := range n[k] {
//Debug:
fmt.Printf("%s, %g\n", s, k)
if len(a) > 3 {
time = (3 * min2) + min1 + a[3] //Formula for minimum time in case of 4 people
} else if len(a) == 3 {
time = min1 + min2 + min3
} else {
fmt.Println("Enter valid arguments in config.yaml")
}
}
}
fmt.Printf("Minimum time taken to cross the bridge is:\t%g\n", time)
}
Playground: https://play.golang.org/p/ObTVA8gk0mg
Config.yaml is:
person:
person_1: 2
person_2: 1
person_3: 5
person_4: 8
person_5: 9
One could run this as: 'go run main.go config.yaml'.
My scenario is that there could be 4,5 or 'n' number of people given in this yaml. Then what would be the minimum time for them to cross the bridge given the constraints.
I think the original problem is a bit more interesting than the one stated (yes, there has to be a Torch in the "Bridge and Torch" problem!).
Based on the Wikipedia description, for example,
Four people come to a river in the night. There is a narrow bridge, but it can only hold two people at a time. They have one torch and, because it's night, the torch has to be used when crossing the bridge. Person A can cross the bridge in 1 minute, B in 2 minutes, C in 5 minutes, and D in 8 minutes. When two people cross the bridge together, they must move at the slower person's pace. The question is, can they all get across the bridge if the torch lasts only 15 minutes?
In our case, of course, there are N people instead of just four, and it takes them variable amount of time to cross the bridge, but the rest of the story is the same.
Here's the implementation:
import (
"fmt"
"sort"
)
func minCrossingTime(x []int) int {
if len(x) == 1 {
return x[0]
}
sort.Ints(x)
t := 0
a, b := x[0], x[1]
x = x[2:]
for len(x) >= 2 {
n := len(x)
c, d := x[n-2], x[n-1]
x = x[:n-2]
t1 := 2*b + a + d
t2 := d + c + 2*a
if t1 < t2 {
t += t1
} else {
t += t2
}
}
if len(x) == 1 {
c := x[0]
t += a + b + c
} else {
t += b
}
return t
}
func main() {
x1 := []int{1, 2, 5, 8}
fmt.Printf("x = %x, time = %d\n", x1, minCrossingTime(x1))
x2 := []int{3, 8, 1, 6, 2, 9}
fmt.Printf("x = %x, time = %d\n", x2, minCrossingTime(x2))
}
Output:
x = [1 2 5 8], time = 15
x = [1 2 3 6 8 9], time = 27
Note: the first example [1 2 5 8] is straight from the Wikipedia, so the answer is yes, they can cross in 15 minutes
Key idea:
Definitions:
Let X = [X1,X2,...,XN] be the sorted array of crossing times with X1 being the fastest and XN the slowest
Let's denote as {XI,XJ} crossing by the pair of people XI and XJ, and {XK} crossing by one person XK, with +{...} indicating the crossing in the desired direction and -{...} in the opposite direction
Logic:
If N < 4 the problem is trivial:
N = 1 => t = X1 (+{X1})
N = 2 => t = X2 (+{X1,X2})
N = 3 => t = X1 + X2 + X3 (+{X1,X2} -{X1} + {X1,X3})
If N >= 4 consider the following problem: how to make two slowest people (and only them) cross the bridge and have the torch brought back in minimal time. There are two "good" ways to do it, with times
t1 = X1 + 2*X2 + XN (+{X1,X2} -{X1} +{X[N-1],XN} -{X2}) and
t2 = 2*X1 + X[N-1] + XN (+{X1,X[N-1]} -{X1} +{X1,XN} -{X1}), so we choose the best (minimum) out of these two
Now the two slowest have crossed the bridge, and the torch is on the same side where it started, so we are left with the original problem for X' = [X1, X2, ..., X[N-2]], which can be solved iteratively by applying the same logic and summing up the crossing times
Extras:
For mathematical proof and more context see e.g. https://page.mi.fu-berlin.de/rote/Papers/pdf/Crossing+the+bridge+at+night.pdf
Code golf solutions in different programming languages: https://codegolf.stackexchange.com/questions/75615/the-bridge-and-torch-problem
Problem: Given an array of positive distinct integer denoting the
crossing time of ‘n’ people. These ‘n’ people are standing at one side
of bridge. Bridge can hold at max two people at a time. When two
people cross the bridge, they must move at the slower person’s pace.
Find the minimum total time in which all persons can cross the bridge.
person:
person_1: 2
person_2: 1
person_3: 5
person_4: 8
person_5: 9
Your algorithm looks complicated.
For example,
package main
import (
"fmt"
"sort"
)
func minCrossingTime(people []int) int {
sort.Slice(people, func(i, j int) bool {
return people[i] > people[j]
})
min := 0
for i := 0; i < len(people); i += 2 {
min += people[i]
}
return min
}
func main() {
people := []int{2, 1, 5, 8, 9}
fmt.Println(len(people), people)
crossingTime := minCrossingTime(people)
fmt.Println(len(people), people)
fmt.Println(crossingTime)
}
Playground: https://play.golang.org/p/pXdGcinwxr-
Output:
5 [2 1 5 8 9]
5 [9 8 5 2 1]
15

Golang: Find two number index where the sum of these two numbers equals to target number

The problem is: find the index of two numbers that nums[index1] + nums[index2] == target. Here is my attempt in golang (index starts from 1):
package main
import (
"fmt"
)
var nums = []int{0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 25182, 25184, 25186, 25188, 25190, 25192, 25194, 25196} // The number list is too long, I put the whole numbers in a gist: https://gist.github.com/nickleeh/8eedb39e008da8b47864
var target int = 16021
func twoSum(nums []int, target int) (int, int) {
if len(nums) <= 1 {
return 0, 0
}
hdict := make(map[int]int)
for i := 1; i < len(nums); i++ {
if val, ok := hdict[nums[i+1]]; ok {
return val, i + 1
} else {
hdict[target-nums[i+1]] = i + 1
}
}
return 0, 0
}
func main() {
fmt.Println(twoSum(nums, target))
}
The nums list is too long, I put it into a gist:
https://gist.github.com/nickleeh/8eedb39e008da8b47864
This code works fine, but I find the return 0,0 part is ugly, and it runs ten times slower than the Julia translation. I would like to know is there any part that is written terrible and affect the performance?
Edit:
Julia's translation:
function two_sum(nums, target)
if length(nums) <= 1
return false
end
hdict = Dict()
for i in 1:length(nums)
if haskey(hdict, nums[i])
return [hdict[nums[i]], i]
else
hdict[target - nums[i]] = i
end
end
end
In my opinion if no elements found adding up to target, best would be to return values which are invalid indices, e.g. -1. Although returning 0, 0 would be enough as a valid index pair can't be 2 equal indices, this is more convenient (because if you forget to check the return values and you attempt to use the invalid indices, you will immediately get a run-time panic, alerting you not to forget checking the validity of the return values). As so, in my solutions I will get rid of that i + 1 shifts as it makes no sense.
Benchmarking of different solutions can be found at the end of the answer.
If sorting allowed:
If the slice is big and not changing, and you have to call this twoSum() function many times, the most efficient solution would be to sort the numbers simply using sort.Ints() in advance:
sort.Ints(nums)
And then you don't have to build a map, you can use binary search implemented in sort.SearchInts():
func twoSumSorted(nums []int, target int) (int, int) {
for i, v := range nums {
v2 := target - v
if j := sort.SearchInts(nums, v2); v2 == nums[j] {
return i, j
}
}
return -1, -1
}
Note: Note that after sorting, the indices returned will be indices of values in the sorted slice. This may differ from indices in the original (unsorted) slice (which may or may not be a problem). If you do need indices from the original order (original, unsorted slice), you may store sorted and unsorted index mapping so you can get what the original index is. For details see this question:
Get the indices of the array after sorting in golang
If sorting is not allowed:
Here is your solution getting rid of that i + 1 shifts as it makes no sense. Slice and array indices are zero based in all languages. Also utilizing for ... range:
func twoSum(nums []int, target int) (int, int) {
if len(nums) <= 1 {
return -1, -1
}
m := make(map[int]int)
for i, v := range nums {
if j, ok := m[v]; ok {
return j, i
}
m[target-v] = i
}
return -1, -1
}
If the nums slice is big and the solution is not found fast (meaning the i index grows big) that means a lot of elements will be added to the map. Maps start with small capacity, and they are internally grown if additional space is required to host many elements (key-value pairs). An internal growing requires rehashing and rebuilding with the already added elements. This is "very" expensive.
It does not seem significant but it really is. Since you know the max elements that will end up in the map (worst case is len(nums)), you can create a map with a big-enough capacity to hold all elements for the worst case. The gain will be that no internal growing and rehashing will be required. You can provide the initial capacity as the second argument to make() when creating the map. This speeds up twoSum2() big time if nums is big:
func twoSum2(nums []int, target int) (int, int) {
if len(nums) <= 1 {
return -1, -1
}
m := make(map[int]int, len(nums))
for i, v := range nums {
if j, ok := m[v]; ok {
return j, i
}
m[target-v] = i
}
return -1, -1
}
Benchmarking
Here's a little benchmarking code to test execution speed of the 3 solutions with the input nums and target you provided. Note that in order to test twoSumSorted(), you first have to sort the nums slice.
Save this into a file named xx_test.go and run it with go test -bench .:
package main
import (
"sort"
"testing"
)
func BenchmarkTwoSum(b *testing.B) {
for i := 0; i < b.N; i++ {
twoSum(nums, target)
}
}
func BenchmarkTwoSum2(b *testing.B) {
for i := 0; i < b.N; i++ {
twoSum2(nums, target)
}
}
func BenchmarkTwoSumSorted(b *testing.B) {
sort.Ints(nums)
b.ResetTimer()
for i := 0; i < b.N; i++ {
twoSumSorted(nums, target)
}
}
Output:
BenchmarkTwoSum-4 1000 1405542 ns/op
BenchmarkTwoSum2-4 2000 722661 ns/op
BenchmarkTwoSumSorted-4 10000000 133 ns/op
As you can see, making a map with big enough capacity speeds up: it runs twice as fast.
And as mentioned, if nums can be sorted in advance, that is ~10,000 times faster!
If nums is always sorted, you can do a binary search to see if the complement to whichever number you're on is also in the slice.
func binary(haystack []int, needle, startsAt int) int {
pivot := len(haystack) / 2
switch {
case haystack[pivot] == needle:
return pivot + startsAt
case len(haystack) <= 1:
return -1
case needle > haystack[pivot]:
return binary(haystack[pivot+1:], needle, startsAt+pivot+1)
case needle < haystack[pivot]:
return binary(haystack[:pivot], needle, startsAt)
}
return -1 // code can never fall off here, but the compiler complains
// if you don't have any returns out of conditionals.
}
func twoSum(nums []int, target int) (int, int) {
for i, num := range nums {
adjusted := target - num
if j := binary(nums, adjusted, 0); j != -1 {
return i, j
}
}
return 0, 0
}
playground example
Or you can use sort.SearchInts which implements binary searching.
func twoSum(nums []int, target int) (int, int) {
for i, num := range nums {
adjusted := target - num
if j := sort.SearchInts(nums, adjusted); nums[j] == adjusted {
// sort.SearchInts returns the index where the searched number
// would be if it was there. If it's not, then nums[j] != adjusted.
return i, j
}
}
return 0, 0
}

How to remove items from a slice while ranging over it?

What is the best way to remove items from a slice while ranging over it?
For example:
type MultiDataPoint []*DataPoint
func (m MultiDataPoint) Json() ([]byte, error) {
for i, d := range m {
err := d.clean()
if ( err != nil ) {
//Remove the DP from m
}
}
return json.Marshal(m)
}
As you have mentioned elsewhere, you can allocate new memory block and copy only valid elements to it. However, if you want to avoid the allocation, you can rewrite your slice in-place:
i := 0 // output index
for _, x := range s {
if isValid(x) {
// copy and increment index
s[i] = x
i++
}
}
// Prevent memory leak by erasing truncated values
// (not needed if values don't contain pointers, directly or indirectly)
for j := i; j < len(s); j++ {
s[j] = nil
}
s = s[:i]
Full example: http://play.golang.org/p/FNDFswPeDJ
Note this will leave old values after index i in the underlying array, so this will leak memory until the slice itself is garbage collected, if values are or contain pointers. You can solve this by setting all values to nil or the zero value from i until the end of the slice before truncating it.
I know its answered long time ago but i use something like this in other languages, but i don't know if it is the golang way.
Just iterate from back to front so you don't have to worry about indexes that are deleted. I am using the same example as Adam.
m = []int{3, 7, 2, 9, 4, 5}
for i := len(m)-1; i >= 0; i-- {
if m[i] < 5 {
m = append(m[:i], m[i+1:]...)
}
}
There might be better ways, but here's an example that deletes the even values from a slice:
m := []int{1,2,3,4,5,6}
deleted := 0
for i := range m {
j := i - deleted
if (m[j] & 1) == 0 {
m = m[:j+copy(m[j:], m[j+1:])]
deleted++
}
}
Note that I don't get the element using the i, d := range m syntax, since d would end up getting set to the wrong elements once you start deleting from the slice.
Here is a more idiomatic Go way to remove elements from slices.
temp := s[:0]
for _, x := range s {
if isValid(x) {
temp = append(temp, x)
}
}
s = temp
Playground link: https://play.golang.org/p/OH5Ymsat7s9
Note: The example and playground links are based upon #tomasz's answer https://stackoverflow.com/a/20551116/12003457
One other option is to use a normal for loop using the length of the slice and subtract 1 from the index each time a value is removed. See the following example:
m := []int{3, 7, 2, 9, 4, 5}
for i := 0; i < len(m); i++ {
if m[i] < 5 {
m = append(m[:i], m[i+1:]...)
i-- // -1 as the slice just got shorter
}
}
I don't know if len() uses enough resources to make any difference but you could also run it just once and subtract from the length value too:
m := []int{3, 7, 2, 9, 4, 5}
for i, s := 0, len(m); i < s; i++ {
if m[i] < 5 {
m = append(m[:i], m[i+1:]...)
s--
i--
}
}
Something like:
m = append(m[:i], m[i+1:]...)
You don't even need to count backwards but you do need to check that you're at the end of the array where the suggested append() will fail. Here's an example of removing duplicate positive integers from a sorted list:
// Remove repeating numbers
numbers := []int{1, 2, 3, 3, 4, 5, 5}
log.Println(numbers)
for i, numbersCount, prevNum := 0, len(numbers), -1; i < numbersCount; numbersCount = len(numbers) {
if numbers[i] == prevNum {
if i == numbersCount-1 {
numbers = numbers[:i]
} else {
numbers = append(numbers[:i], numbers[i+1:]...)
}
continue
}
prevNum = numbers[i]
i++
}
log.Println(numbers)
Playground: https://play.golang.org/p/v93MgtCQsaN
I just implement a method which removes all nil elements in slice.
And I used it to solve a leetcode problems, it works perfectly.
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func removeNil(lists *[]*ListNode) {
for i := 0; i < len(*lists); i++ {
if (*lists)[i] == nil {
*lists = append((*lists)[:i], (*lists)[i+1:]...)
i--
}
}
}
You can avoid memory leaks, as suggested in #tomasz's answer, controlling the capacity of the underlying array with a full slice expression. Look at the following function that remove duplicates from a slice of integers:
package main
import "fmt"
func removeDuplicates(a []int) []int {
for i, j := 0, 1; i < len(a) && j < len(a); i, j = i+1, j+1 {
if a[i] == a[j] {
copy(a[j:], a[j+1:])
// resize the capacity of the underlying array using the "full slice expression"
// a[low : high : max]
a = a[: len(a)-1 : len(a)-1]
i--
j--
}
}
return a
}
func main() {
a := []int{2, 3, 3, 3, 6, 9, 9}
fmt.Println(a)
a = removeDuplicates(a)
fmt.Println(a)
}
// [2 3 3 3 6 9 9]
// [2 3 6 9]
For reasons #tomasz has explained, there are issues with removing in place. That's why it is practice in golang not to do that, but to reconstruct the slice. So several answers go beyond the answer of #tomasz.
If elements should be unique, it's practice to use the keys of a map for this. I like to contribute an example of deletion by use of a map.
What's nice, the boolean values are available for a second purpose. In this example I calculate Set a minus Set b. As Golang doesn't have a real set, I make sure the output is unique. I use the boolean values as well for the algorithm.
The map gets close to O(n). I don't know the implementation. append() should be O(n). So the runtime is similar fast as deletion in place. Real deletion in place would cause a shifting of the upper end to clean up. If not done in batch, the runtime should be worse.
In this special case, I also use the map as a register, to avoid a nested loop over Set a and Set b to keep the runtime close to O(n).
type Set []int
func differenceOfSets(a, b Set) (difference Set) {
m := map[int]bool{}
for _, element := range a {
m[element] = true
}
for _, element := range b {
if _, registered := m[element]; registered {
m[element] = false
}
}
for element, present := range m {
if present {
difference = append(difference, element)
}
}
return difference
}
Try Sort and Binary search.
Example:
package main
import (
"fmt"
"sort"
)
func main() {
// Our slice.
s := []int{3, 7, 2, 9, 4, 5}
// 1. Iterate over it.
for i, v := range s {
func(i, v int) {}(i, v)
}
// 2. Sort it. (by whatever condition of yours)
sort.Slice(s, func(i, j int) bool {
return s[i] < s[j]
})
// 3. Cut it only once.
i := sort.Search(len(s), func(i int) bool { return s[i] >= 5 })
s = s[i:]
// That's it!
fmt.Println(s) // [5 7 9]
}
https://play.golang.org/p/LnF6o0yMJGT

Resources