作為一名coder,演算法不僅要會懂會寫,在保證結果正確的同時,還要求效能足夠高,才稱得上優秀的演算法。
本文比較了本人用 golang
初練演算法的一些 demo
,以期不斷進步,假以時日,寫出更好的演算法。
1. 求眾數(在陣列中出現次數大於 n/2 的元素)
a. 本人寫法:
func majorityElement1(nums []int) int {
n := len(nums)
for i := 0; i < n; i++ {
equalNum := 1
for j := 0; j < n; j++ {
if nums[i] == nums[j] && i != j {
equalNum++
}
if equalNum > n/2 {
return nums[i]
}
}
}
return nums[0]
}
複製程式碼
b. 別人優秀寫法:
func majorityElement2(nums []int) int {
middle := len(nums) / 2
equalMap := make(map[int]int, middle)
for _, v := range nums {
equalMap[v] += 1
if equalMap[v] > middle {
return v
}
}
return nums[0]
}
複製程式碼
2. 只出現一次的數字
a. 本人寫法:
func singleNumber1(nums []int) int {
n := len(nums)
for i := 0; i < n; i++ {
for j := 0; j < n; j++ {
if nums[i] == nums[j] && i != j {
break
}
if j == (n - 1) {
return nums[i]
}
}
}
return nums[n-1]
}
複製程式碼
b. 別人優秀寫法:
func singleNumber2(nums []int) int {
// 零和任何數異或都等於任何數, 一個數異或兩次就等於0
// 本題中除一個之外每個元素都出現兩次
// 所以用迴圈異或所有數就等於 只出現一次的那個數
ret := 0
for _, v := range nums {
ret ^= v
}
return ret
}
複製程式碼
3. 搜尋二位矩陣中的值
a. 本人寫法:
func searchMatrix1(matrix [][]int, target int) bool {
ret := false
for i, _ := range matrix {
if ret {
break
}
for _, inValue := range matrix[i] {
if inValue == target {
ret = true
break
}
}
}
return ret
}
複製程式碼
b. 別人優秀寫法:
func searchMatrix2(matrix [][]int, target int) bool {
if len(matrix) == 0 {
return false
}
row, col := len(matrix), len(matrix[0])
i, j := 0, col-1
for i < row && j >= 0 {
if matrix[i][j] == target {
return true
}
if matrix[i][j] > target {
j--
} else if matrix[i][j] < target {
i++
}
}
return false
}
複製程式碼
4. 合併兩個有序陣列
a. 本人寫法:
func merge1(nums1 []int, m int, nums2 []int, n int) {
nonZero := 0
for i, _ := range nums1 {
if nums1[i] != 0 {
nonZero = i
break
}
}
length := len(nums1)
for i := 0; i < length; i++ {
if nums1[i] == 0 {
if length == 1 {
nums1 = []int{}
break
}
if i > nonZero {
nums1 = append(nums1[:i], nums1[i+1:]...)
i--
}
length = len(nums1)
}
}
m = len(nums1)
if m <= 0 || len(nums1) == 0 {
nums1 = append(nums1, nums2...)
} else {
for i := 0; i < m; i++ {
if len(nums1) == m+n {
break
}
for index := 0; index < n; index++ {
// corner case
if nums2[0] >= nums1[m-1] && i == 0 && index == 0 {
nums1 = append(nums1, nums2...)
break
}
if nums2[n-1] <= nums1[0] && i == 0 && index == 0 {
nums1 = append(nums2, nums1...)
break
}
if nums2[index] > nums1[i] {
if i == len(nums1)-1 {
nums1 = append(nums1, nums2[index:]...)
break
}
i++
if index != n-1 {
index--
} else {
nums1 = append(nums1, nums2[n-1])
break
}
continue
}
if nums2[index] == nums1[i] {
rear := append([]int{}, nums1[i+1:]...)
nums1 = append(nums1[0:i+1], nums2[index])
nums1 = append(nums1, rear...)
i++
continue
}
if nums2[index] < nums1[i] {
if index == 0 && i == 0 {
nums1 = append([]int{nums2[index]}, nums1...)
} else {
rear := append([]int{}, nums1[i:]...)
nums1 = append(nums1[0:i], nums2[index])
nums1 = append(nums1, rear...)
}
i++
continue
}
}
}
}
fmt.Println(nums1)
}
複製程式碼
b. 別人優秀寫法:
func merge2(nums1 []int, m int, nums2 []int, n int) {
for i := 0; i < n; i++ {
nums1[m+i] = nums2[i]
}
sort.Sort(sort.IntSlice(nums1))
fmt.Println(nums1)
}
複製程式碼
這個題目,自己花了很多時間才寫出來,看了別人的寫法後,反思自己怎麼沒有想到用 golang
自帶的排序函式 : (
所以做事情之前要先想到是否別人已經有造好的輪子(當然輪子要是已經被廣泛認可的)可用,站在巨人的肩膀上才能走的更遠。
小結:
從以上例子看出,在寫演算法,我目前的思路總是想著迴圈巢狀去實現,雖然能計算出正確的結果,但效能很低,所以需要不斷學習別人優秀的演算法思路,不斷動手練習,期望以後也可以隨手寫出優秀的演算法。
祝大家週末愉快~