「这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战」
剑指 Offer 15 二进制中1的个数
题目描述
解题思路
方法1
将n与2^i按位与,如果结果不为0,则说明n的第i位为1(i从0开始计数)
代码
var hammingWeight = function(n) {
let res = 0
for (let i = 0; i < 32; i++) {
if ((n & (1 << i)) !== 0) {
res++
}
}
return res
};
复杂度
- 时间复杂度:O(k),其中 k 是int 型的二进制位数,k=32。我们需要检查 n 的二进制位的每一位,一共需要检查 32 位。
- 空间复杂度:O(1)
方法2
n&(n-1)相当于将n的最低位为1的那一位变为0,于是运算几次就说明n有几个1
代码
var hammingWeight = function(n) {
let res = 0
while (n !== 0) {
n = n & (n - 1)
res++
}
return res
};
复杂度
- 时间复杂度:O(logn)
- 空间复杂度:O(1)
方法3
代码
var hammingWeight = function(n) {
return n.toString(2).split('0').join('').length
};
剑指 Offer 38 字符串的排列
问题描述
解题思路
- 将字符数组按字典序进行排列
- 找出字典序仅高于当前字符数组的下一个排列,方法如下:
- 从右向左找出第一个顺序对
arr[i] < arr[j] - 此时
arr[i]右边的序列必为降序 - 交换
arr[i]和arr[j],交换后arr[i]右边的序列仍为降序 - 将
arr[i]右边的序列按升序排列,此时得到的序列为字典序仅高于前面序列的序列
- 从右向左找出第一个顺序对
- 按上述步骤按顺序找出所有序列
代码
/**
* @param {string} s
* @return {string[]}
*/
var permutation = function(s) {
const swap = (arr, i, j) => {
let temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
}
const reverse = (arr, start) => {
let left = start
let right = arr.length - 1
while (left < right) {
swap(arr, left, right)
left++
right--
}
}
const nextPermutation = (arr) => {
let i = arr.length - 2
while (i >= 0 && arr[i] >= arr[i + 1]) {
i--
}›
if (i < 0) {
return false
}
let j = arr.length - 1
while (arr[i] >= arr[j]) {
j--
}
swap(arr, i, j)
reverse(arr, i + 1)
return true
}
let res = []
let arr = Array.from(s).sort()
do {
res.push(arr.join(''))
} while (nextPermutation(arr))
return res
};
算法复杂度分析
- 时间复杂度:O(n * n!),需要O(nlogn)得到第一个排列,nextPermutation的时间复杂度为O(n),全排列的总数为n!,所以总时间复杂度为O(n * n!)
- 空间复杂度:O(1)