小米OJ-20題-Go

小米OJ第20題Go語言實現:

問題鏈接:https://code.mi.com/problem/list/view?id=20

描述
等差數列是常見數列的一種,如果一個數列從第二項起,每一項與它的前一項的差等於同一個常數,這個數列就叫做等差數列,而這個常數叫做等差數列的公差,公差常用字母d表示。即對於數列S,它滿足了(S[i]-S[i-1]) = d (i \gt 1)(S[i]−S[i−1])=d(i>1)。 顯然,一個數字無法構成等差數列,而任意兩個數字可以形成一個等差數列。 這裏給出了一個長度爲N (0 \lt N \lt 200)N(0<N<200)的數字序列,每個位置有一個整數(-100 \le \text{整數} \le 100)(−100≤整數≤100),需要找到這個數字序列裏包含多少個等差數列,序列順序固定,無需排序。 輸入數據格式:\text{S[0] S[1] S[2] … S[N]}S[0] S[1] S[2] … S[N](以半角空格符分隔,N \gt 1N>1) 輸出數據格式:等差數列數量 MM; 其中數列 SS 的項爲整數

請注意時間複雜度的限制。

輸入
輸入一個數列[ 2 7 4 5 6 ],該數列包含等差數列: [ 2 7 ] [ 2 4 ] [ 2 5 ] [ 2 6 ] [ 7 4 ] [ 7 5 ] [ 7 6 ] [ 4 5 ] [ 4 6 ] [ 5 6 ] [ 2 4 6 ] [ 4 5 6 ]

輸出
上例共包含12組等差數列,故應輸出12

輸入樣例
2 7 4 5 6
3 3 3 3
複製樣例
輸出樣例
12
11

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func solution20(line string) string {
	numberArrray := strings.Split(line, " ")
	numbers := make([]int, len(numberArrray))
	for i, v := range numberArrray {
		numbers[i], _ = strconv.Atoi(v)
	}
	var result = 0
	listArray := make([][]*int, 0)
	tempResult := make([]*int, 0)
	DFS(listArray, tempResult, numbers, 0, &result);
	return strconv.Itoa(result)
}

func DFS(resultArray [][]*int, tempArray []*int, numbers []int, start int, result *int) {
	resultArray = append(resultArray, tempArray)
	judgeResult := isCorrectArray(tempArray)
	if !judgeResult && len(tempArray) > 2 {
		return
	}
	if judgeResult{
		*result = *result + 1
	}
	for i := start; i < len(numbers); i++ {
		tempArray = append(tempArray, &numbers[i])
		DFS(resultArray, tempArray, numbers, i+1, result);
		tempArray = tempArray[:len(tempArray)-1]
	}
}

func isCorrectArray(args []*int) bool {
	if len(args) <= 1 {
		return false
	}
	if len(args) == 2 {
		return true
	}
	d := *args[1] - *args[0]
	for i := 2; i < len(args); i++ {
		if *args[i]-*args[i-1] != d {
			return false
		}
	}
	return true
}

func main() {
	r := bufio.NewReaderSize(os.Stdin, 20480)
	for line, _, err := r.ReadLine(); err == nil; line, _, err = r.ReadLine() {
		fmt.Println(solution20(string(line)))
	}
}

在這裏插入圖片描述
此題關鍵點

  1. 排列組合的展示,給定了一個序列,要求輸出所有組合或者序列,這裏沒有順序的要求,故要求展示其所有的組合,共2n12^{n}-1有種。有暴力法、DFS法,二進制法(即01100,代表只有第2和第3個,每次二進制加1,即得到一種組合)(歡迎補充)
  2. 數組的判定,只需根據等差數組的定義來即可
  3. 時間複雜度要求,起初的思路是找出所有的組合情況,最後統一判斷,但運行結果超時,即對於序列2 7 4 5 6,先找出所有的可能性,共15種,再對這15種進行判斷,時間複雜度不符合要求。
  4. 採用DFS之後需要進行剪枝,例如2 7 4這樣已經不符合等差數列要求的序列,後面的就不要展示出來了,因爲其肯定不滿足等差數列定義,可以直接砍掉後面的2 7 4 5和2 7 4 6 以及2 7 4 5 6,同理可以減掉多種情況,一方面較少了DFS遍歷的深度即數量,另一方面也減少了等差數組的判定,最終時間複雜度符合要求。

注:
該類問題有多種變體,現記錄如下,之後需要分類解決
5. 全排列問題 {a,b,c},給出所有的排列,共2n12^{n}-1
6. 從M個序列中任取K個,輸出所有的可能性。
7. DFS和BFS
8. 未完待續(…)

DSF的常用場景

  1. 回溯法
  2. 字典序
    例如給定字符數組{‘1’,‘2’,‘3’},按序輸出所有的組合,以字典序輸出,以下給出關鍵代碼
	func DFS(visit []int, tempResult []int, numbers []int, start int) {
	if start == len(numbers) {
		for j := range tempResult {
			fmt.Print("\t", tempResult[j])
		}
		fmt.Println("")
	}

	for i := 0; i < len(numbers); i++ {
		if visit[i] == 0 {
			visit[i] = 1
			tempResult[start] = numbers[i]
			DFS(visit, tempResult, numbers, start+1);
			visit[i] = 0
		}
	}
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章