BaezaYates 交集python和golang代码
def bsearch(find, arr, low, high): while low <= high: mid = (low + high) >> 1 if arr[mid] == find: return mid, True elif arr[mid] > find: high = mid - 1 else: low = mid + 1 return low, False def BaezaYates_intersect_helper(A, B, left1, right1, left2, right2, result): if left1 > right1 or left2 > right2: return if right1-left1 > right2-left2: left1, left2 = left2, left1 right1, right2 = right2, right1 A, B = B, A mid = (left1 + right1) >> 1 index,found = bsearch(A[mid], B, left2, right2) if found: result.append(A[mid]) BaezaYates_intersect_helper(A, B, left1, mid-1, left2, index-1, result) BaezaYates_intersect_helper(A, B, mid+1, right1, index+1, right2, result) else: if A[mid] > B[right2]: BaezaYates_intersect_helper(A, B, left1, mid-1, left2, right2, result) elif A[mid] < B[left2]: BaezaYates_intersect_helper(A, B, mid+1, right1, left2, right2, result) else: BaezaYates_intersect_helper(A, B, left1, mid-1, left2, index-1, result) BaezaYates_intersect_helper(A, B, mid+1, right1, index, right2, result) def BaezaYates_intersect(A, B): result = [] BaezaYates_intersect_helper(A, B, 0, len(A)-1, 0, len(B)-1, result) result.sort() return result from random import randint if __name__ == "__main__": for i in range(2000): A = [randint(0, 100) for i in range(30)] B = [randint(0, 100) for i in range(30)] A.sort() B.sort() #print A #print B inter_set = BaezaYates_intersect(A, B) #print inter_set inter_set2 = set(A) & set(B) for data in inter_set: assert data in inter_set2 print "tests passed..."
对应的go代码:
package main import ( "fmt" "math/rand" "sort" "time" ) func bsearch(find int, arr []int, low int, high int) (int, bool) { for low <= high { mid := (low + high) >> 1 if arr[mid] == find { return mid, true } else if arr[mid] > find { high = mid - 1 } else { low = mid + 1 } } return low, false } func BaezaYatesIntersectHelper(A []int, B []int, left1 int, right1 int, left2 int, right2 int, result *[]int) { if left1 > right1 || left2 > right2 { return } if right1-left1 > right2-left2 { left1, left2 = left2, left1 right1, right2 = right2, right1 A, B = B, A } mid := (left1 + right1) >> 1 index, found := bsearch(A[mid], B, left2, right2) /* if found { fmt.Printf("A[mid]=%d index=%d\n", A[mid], index) } */ if found { *result = append(*result, A[mid]) BaezaYatesIntersectHelper(A, B, left1, mid-1, left2, index-1, result) BaezaYatesIntersectHelper(A, B, mid+1, right1, index+1, right2, result) } else { if A[mid] > B[right2] { BaezaYatesIntersectHelper(A, B, left1, mid-1, left2, right2, result) } else if A[mid] < B[left2] { BaezaYatesIntersectHelper(A, B, mid+1, right1, left2, right2, result) } else { BaezaYatesIntersectHelper(A, B, left1, mid-1, left2, index-1, result) BaezaYatesIntersectHelper(A, B, mid+1, right1, index, right2, result) } } } func BaezaYatesIntersect(A, B []int) []int { result := []int{} BaezaYatesIntersectHelper(A, B, 0, len(A)-1, 0, len(B)-1, &result) sort.Ints(result) return result } func random(min, max int) int { return rand.Intn(max-min) + min } func main() { const SIZE int = 30 for i := 0; i < 2000; i++ { A, B := [SIZE]int{}, [SIZE]int{} rand.Seed(time.Now().Unix()) for j := 0; j < 30; j++ { A[j] = random(0, 100) B[j] = random(0, 100) } sort.Ints(A[:]) sort.Ints(B[:]) fmt.Println(A) fmt.Println(B) inter_set := BaezaYatesIntersect(A[:], B[:]) fmt.Println(inter_set) /* inter_set2 = set(A) & set(B) for data in inter_set: assert data in inter_set2 */ } fmt.Printf("tests passed...\n") }
牢记go语言中:
(1)要修改函数输入的slice参数,必须通过指针才能搞定,比如
func BaezaYatesIntersectHelper(A []int, B []int, left1 int, right1 int, left2 int, right2 int, result *[]int)
最后一个参数!如果去掉指针,则无任何append效果!
(2)slice本质是array的内存引用!修改它必然会影响到array!因此,
sort.Ints(A[:]) 可以实现数组排序!