问:
- 给定一个字符串str,可以通过移除字符使得str变成回文串。问有多少种移除方案
- 在一个无序数组中,求第k小的数
- 假设正数1,裂开的方式有一种:1;正数2:(1,1),(2);正数3:(1,1,1),(1,2),(3)。正数4:(1,1,1,1),(1,3),(2,2),(4)。给定一个正数n,求裂开的方法数
解:
- 相当于求有多少个回文子序列
function getAllNums(str) {
const dp = []
for (let i = 0; i <str.length; i++) {
dp[i] = []
for (let j = 0; j < str.length; j++) {
if (i > j) {
dp[i][j] = 0
}
if (i === j) {
dp[i][j] = 1
}
}
}
for (let i = str.length - 2; i >= 0; i--) {
for (let j = i + 1; j < str.length; j++) {
dp[i][j] = dp[i][j - 1] + dp[i + 1][j] - dp[i + 1][j - 1]
if (str[i] === str[j]) {
dp[i][j] += dp[i + 1][j - 1] + 1
}
}
}
return dp[0][str.length - 1]
}
// 基于快排的方法
function findKthNum(arr, k) {
function getRes(left, right) {
if (left >= right) return
const target = arr[Math.floor((Math.random() * (right - left) + left))]
const { smallIdx, bigIdx } = partition(left, right, target)
if (k > smallIdx && k <= bigIdx) {
return arr.slice(0, k)
}
if (k <= smallIdx) {
return getRes(left, smallIdx)
} else {
return getRes(bigIdx, right)
}
}
return getRes(0, arr.length - 1)
function partition(left, right, target) {
let smallIdx = left - 1
let bigIdx = right + 1
let pos = left
while (pos < bigIdx) {
if (arr[pos] < target) {
[arr[smallIdx + 1], arr[pos]] = [arr[pos], arr[smallIdx + 1]]
smallIdx++
pos++
} else if (arr[pos] === target) {
pos++
} else {
[arr[bigIdx - 1], arr[pos]] = [arr[pos], arr[bigIdx - 1]]
bigIdx--
}
}
return {
smallIdx,
bigIdx
}
}
}
function getAllNums(n) {
const dp = []
for (let i = 0; i <= n; i++) {
dp[i] = []
for (let j = 0; j <= n; j++) {
if (j === 0 || i === j) {
dp[i][j] = 1
continue
}
if (i > j) {
dp[i][j] = 0
}
}
}
for (let i = n - 1; i >= 1; i--) {
for (let j = i + 1; j <= n; j++) {
dp[i][j] = 0
dp[i][j] = dp[i + 1][j] + dp[i][j - i]
}
}
return dp[1][n]
}