记一次leetcode解题

题目是这样的:

Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.python

For example, given n = 3, a solution set is:数组

[
  "((()))",
  "(()())",
  "(())()",
  "()(())",
  "()()()"
]
复制代码

简单翻译过来就是,写出n对括号的全部组合状况,注意是well-formed的组合。bash

这题目,so easy啊。app

个人思路以下,很明显么,这是一个排列组合的题目。n对括号,一共是2n个位置,也就是说在2n个位置里面,找n个位置放(,另外n个位置放),这就是一个C(n,m)的数学问题。在全部的组合里找出来well-formed的组合,不就Ok了嘛,哈哈哈我可真是个小天才。less

首先要实现C(n,m)的代码,也就是n个数里,取m个数的全部状况。而后...好难啊,木有思路。通过左思右想加百度谷歌。找到一个方法,使用递归的方式。先拿出第一个数,而后再从剩下的n-1个数去递归查找,就变成了一个C(n-1,m-1)的子问题。这里用了一个维数组去存每种状况的组合,用了一个结构体使用二维数组去存全部的组合状况。代码以下。ui

type TwoDArray struct {
	arrays [][]int
}

func getItems(data []int, n int, outlen int, startIndex int, m int, array []int, arrIndex int, finalArray *TwoDArray) {
	if m == 0 {
		a := []int{}
		for i := 0; i < outlen; i++ {
			//fmt.Printf("%d \t", arry[i])
			a = append(a, array[i])
		}
		finalArray.arrays = append(finalArray.arrays, a)
		return
	}
	endIndex := n - m
	for i := startIndex; i <= endIndex; i++ {
		array[arrIndex] = data[i]
		getItems(data, n, outlen, i+1, m-1, array, arrIndex+1, finalArray)
	}
}
复制代码

ok,拿到全部组合了以后就好作了。咱们按照位置的索引,将对应的位置进行替换就行了,先设置初始的串是2n个"(",而后把对应位置的"("替换成")",再验证一下是不是well-formed的就能够了,所有代码以下spa

func match(a byte, b byte) bool {
	if a == '(' && b == ')' {
		return true
	}
	if a == '{' && b == '}' {
		return true
	}
	if a == '[' && b == ']' {
		return true
	}
	return false
}

func isValid(s string) bool {

	l := []byte{}
	top := -1

	for i := 0; i < len(s); i++ {
		if top == -1 && i == 0 {
			top += 1
			l = append(l, s[i])
			continue
		}
		if top >= 0 {
			if match(l[top], s[i]) {
				l = l[:top]
				top -= 1
			} else {
				top += 1
				l = append(l, s[i])
			}
		} else {
			top += 1
			l = append(l, s[i])
		}
	}

	if len(l) == 0 {
		return true
	}

	return false
}

type TwoDArray struct {
	arrays [][]int
}

func getItems(data []int, n int, outlen int, startIndex int, m int, array []int, arrIndex int, finalArray *TwoDArray) {
	if m == 0 {
		a := []int{}
		for i := 0; i < outlen; i++ {
			//fmt.Printf("%d \t", arry[i])
			a = append(a, array[i])
		}
		finalArray.arrays = append(finalArray.arrays, a)
		return
	}
	endIndex := n - m
	for i := startIndex; i <= endIndex; i++ {
		array[arrIndex] = data[i]
		getItems(data, n, outlen, i+1, m-1, array, arrIndex+1, finalArray)
	}
}

func generateParenthesis(n int) []string {
	res := make([]string, 0)
	if n == 0 {
		return []string{"()"}
	}
	initStr := ""

	data := []int{}

	for i := 0; i < 2*n; i++ {
		initStr += "("
		data = append(data, i+1)
	}

	//组合用一个二进制数表示
	arr := make([]int, n)
	finalArry := &TwoDArray{}
	getItems(data, len(data), n, 0, n, arr, 0, finalArry)

	for i := 0; i < len(finalArry.arrays); i++ {
		tmp := initStr
		for _, m := range finalArry.arrays[i] {

			pos := m - 1
			tmp = tmp[:pos] + ")" + tmp[pos+1:]
		}
		if isValid(tmp) {
			res = append(res, tmp)
		}
	}

	return res
}

func main() {
	a := generateParenthesis(3)
	fmt.Println(a)
}
复制代码

洋洋洒洒写了100行代码,提交上去验证一下翻译

Runtime: 12 ms, faster than 21.43% of Go online submissions for Generate Parentheses.
Memory Usage: 8.4 MB, less than 15.87% of Go online submissions for Generate Parentheses.
复制代码

虽然经过了,可是时间复杂度和空间复杂度都过高了。我去看一看leetcode上的solution。第一种方法是纯暴力解法直接找出全部组合。第二种解法以下,它的python代码只有14行,我意识到我这是跑偏到北极去了。我确定是想不出来这种方法的,它的思路就是记录左括号和右括号的数量,每次都是以一个左括号开始,若是右括号数量少的话就加一个右括号,以此来保证括号形式有效(well-formed),最后达到长度时候,把结果存下来。code

class Solution(object):
    def generateParenthesis(self, N):
        ans = []
        def backtrack(S = '', left = 0, right = 0):
            if len(S) == 2 * N:
                ans.append(S)
                return
            if left < N:
                backtrack(S+'(', left+1, right)
            if right < left:
                backtrack(S+')', left, right+1)

        backtrack()
        return ans
复制代码

好吧,我已经开始严重怀疑个人智商了,我可能不适合作leetcode题目啊。orm

总结一下,其实题目并非很难,可能须要一些技巧性的思路。我一般都是按照常规思路去解决问题的,看到问题的时候首先会使用暴力方法,可是确定会有一些更节省时间和空间的办法。一般是用空间换时间,或者是利用规律或者数学公式,或者是采起分治的策略。平时仍是要多刷一些题目进行练习来提升本身的思考能力和思惟方式。

相关文章
相关标签/搜索