Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 155 additions & 0 deletions design-hit-counter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
package main

import (
"fmt"
)

const (
MaxNumCounts = 300
)

type HitCounter struct {
head int
vHead int
tail int
vTail int
counts []int
}

/** Initialize your data structure here. */
func Constructor() HitCounter {
return HitCounter{
head: MaxNumCounts - 1,
vHead: MaxNumCounts,
tail: 0,
vTail: 1,
counts: make([]int, MaxNumCounts),
}
}

func (this *HitCounter) resetCounts() {
for i, _ := range this.counts {
this.counts[i] = 0
}
}

func (this *HitCounter) sum() int {
s := 0

for _, c := range this.counts {
s += c
}

return s
}

/** Record a hit.
@param timestamp - The current timestamp (in seconds granularity). */
func (this *HitCounter) Hit(timestamp int) {
if timestamp-this.vHead >= MaxNumCounts {
this.resetCounts()
this.head = MaxNumCounts - 1
this.tail = 0
this.vHead = timestamp
this.vTail = this.vHead - MaxNumCounts + 1
this.counts[this.head] += 1

return
}

if this.vHead < timestamp {
for this.vHead < timestamp {
this.vHead++
this.vTail++

this.head = (this.head + 1) % MaxNumCounts
this.tail = (this.tail + 1) % MaxNumCounts

this.counts[this.head] = 0
}

this.counts[this.head] = 1

return
}

// this.vHead >= timestamp
offset2 := (this.tail + (timestamp - this.vTail)) % MaxNumCounts
this.counts[offset2] += 1
}

/** Return the number of hits in the past 5 minutes.
@param timestamp - The current timestamp (in seconds granularity).
*/
func (this *HitCounter) GetHits(timestamp int) int {
if timestamp-this.vHead >= MaxNumCounts {
this.resetCounts()
this.head = MaxNumCounts - 1
this.tail = 0
this.vHead = timestamp
this.vTail = this.vHead - MaxNumCounts + 1

return 0
}

if this.vHead < timestamp {
for this.vHead < timestamp {
this.vHead++
this.vTail++

this.head = (this.head + 1) % MaxNumCounts
this.tail = (this.tail + 1) % MaxNumCounts

this.counts[this.head] = 0
}

this.counts[this.head] = 0

return this.sum()
}

// this.vHead >= timestamp
return this.sum()
}

/**
* Your HitCounter object will be instantiated and called as such:
* obj := Constructor();
* obj.Hit(timestamp);
* param_2 := obj.GetHits(timestamp);
*/

func test1() {
hc := Constructor()

hc.Hit(1)
hc.Hit(2)
hc.Hit(3)
fmt.Printf("getHits(4) = %d (expected: 3)\n", hc.GetHits(4))

hc.Hit(300)
fmt.Printf("getHits(300) = %d (expected: 4)\n", hc.GetHits(300))

fmt.Printf("getHits(301) = %d (expected: 3)\n", hc.GetHits(301))
}

func test2() {
hc := Constructor()

hc.Hit(1)
hc.Hit(1)
hc.Hit(1)
hc.Hit(300)
fmt.Printf("getHits(300) = %d (expected: 4)\n", hc.GetHits(300))

hc.Hit(300)
fmt.Printf("getHits(300) = %d (expected: 5)\n", hc.GetHits(300))

hc.Hit(301)
fmt.Printf("getHits(301) = %d (expected: 3)\n", hc.GetHits(301))
}

func main() {
test1()
// test2()
}
52 changes: 52 additions & 0 deletions edit-distance.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package main

func min2(a, b int) int {
if a < b {
return a
}

return b
}

func min3(a, b, c int) int {
return min2(a, min2(b, c))
}

func minDistance(word1 string, word2 string) int {
w1Chars, w2Chars := []rune(word1), []rune(word2)
w1Len, w2Len := len(w1Chars), len(w2Chars)
mat := make([][]int, w1Len+1)

for i, _ := range mat {
mat[i] = make([]int, w2Len+1)
}

// mat[i][j]: the minimum number of edits neeed to transform
// word1's i-prefix (prefix of length i) to word2's j-prefix
// (prefix of length j)
for i := 0; i <= w1Len; i++ {
mat[i][0] = i
}

for j := 0; j <= w2Len; j++ {
mat[0][j] = j
}

for i := 1; i <= w1Len; i++ {
for j := 1; j <= w2Len; j++ {
if w1Chars[i-1] == w2Chars[j-1] {
mat[i][j] = mat[i-1][j-1]

continue
}

mat[i][j] = min3(1+mat[i-1][j-1], 1+mat[i-1][j], 1+mat[i][j-1])
}
}

return mat[w1Len][w2Len]
}

func main() {

}
121 changes: 121 additions & 0 deletions find-all-anagrams-in-a-string.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package main

import (
"fmt"
)

func dumpNonZeroCounts(counts []int) {
for i, count := range counts {
if count == 0 {
continue
}

fmt.Printf("%c: %d; ", rune(i), count)
}

fmt.Println()
}

func findAnagrams(s string, p string) []int {
if len(s) < len(p) {
return []int{}
}

pChars := []rune(p)
sChars := []rune(s)
pCharCounts := make([]int, 256)
sWindowCharCounts := make([]int, 256)

for _, pChar := range pChars {
pCharCounts[pChar] += 1
}

for i := 0; i < len(pChars); i++ {
sWindowCharCounts[sChars[i]] += 1
}

numDiffs := 0

for i := 0; i < len(pCharCounts); i++ {
if pCharCounts[i] != sWindowCharCounts[i] {
numDiffs++
}
}

start, end := 0, len(pChars)-1
anagramOffsets := make([]int, 0, len(pChars))

for end < len(sChars) {
if numDiffs == 0 {
anagramOffsets = append(anagramOffsets, start)
}

sWindowCharCounts[sChars[start]]--

if sWindowCharCounts[sChars[start]] == pCharCounts[sChars[start]] {
numDiffs--
} else if sWindowCharCounts[sChars[start]]+1 == pCharCounts[sChars[start]] {
numDiffs++
}

start++

end++

if end >= len(sChars) {
break
}

sWindowCharCounts[sChars[end]]++

if sWindowCharCounts[sChars[end]] == pCharCounts[sChars[end]] {
numDiffs--
} else if sWindowCharCounts[sChars[end]]-1 == pCharCounts[sChars[end]] {
numDiffs++
}

// fmt.Printf("At start=%d: ", start)
// dumpNonZeroCounts(sWindowCharCounts)
}

return anagramOffsets
}

type testcase struct {
s string
p string
expectedResult []int
}

func slicesEqual(a, b []int) bool {
if len(a) != len(b) {
return false
}

for i, n := range a {
if n != b[i] {
return false
}
}

return true
}

func runTests() {
testcases := []testcase{
testcase{"cbaebabacd", "abc", []int{0, 6}},
testcase{"abab", "ab", []int{0, 1, 2}},
}

for i, tc := range testcases {
result := findAnagrams(tc.s, tc.p)

if !slicesEqual(result, tc.expectedResult) {
fmt.Printf("Test %d failed; expected: %v; got %v\n", i, tc.expectedResult, result)
}
}
}

func main() {
runTests()
}
61 changes: 61 additions & 0 deletions find-if-string-is-k-palindrome-or-not.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package main

import "fmt"

func min2(a, b int) int {
if a < b {
return a
}

return b
}

func min3(a, b, c int) int {
return min2(a, min2(b, c))
}

func minDistance(word1 string, word2 string) int {
w1Chars, w2Chars := []rune(word1), []rune(word2)
w1Len, w2Len := len(w1Chars), len(w2Chars)
mat := make([][]int, w1Len+1)

for i, _ := range mat {
mat[i] = make([]int, w2Len+1)
}

// mat[i][j]: the minimum number of edits neeed to transform
// word1's i-prefix (prefix of length i) to word2's j-prefix
// (prefix of length j)
for i := 0; i <= w1Len; i++ {
mat[i][0] = i
}

for j := 0; j <= w2Len; j++ {
mat[0][j] = j
}

for i := 1; i <= w1Len; i++ {
for j := 1; j <= w2Len; j++ {
if w1Chars[i-1] == w2Chars[j-1] {
mat[i][j] = mat[i-1][j-1]

continue
}

mat[i][j] = min3(1+mat[i-1][j-1], 1+mat[i-1][j], 1+mat[i][j-1])
}
}

return mat[w1Len][w2Len]
}

func runTests() {
fmt.Printf("edits: %d\n", minDistance("abbac", "cabba"))
fmt.Printf("edits: %d\n", minDistance("abcdecba", "abcedcba"))
fmt.Printf("edits: %d\n", minDistance("abcdeca", "acedcba"))

}

func main() {
runTests()
}
Loading