问:
- 旋转矩阵
- 以zigzag方式打印矩阵
- 假设s和m初始化,s='a';m=s;定义两种操作,第一种操作:m = s;s = s + s;第二种操作:s=s+m。求对小操作步骤数,可以将s拼接到长度等于n
- 给定一个字符串类型数组arr,求其中出现次数最多的前K个
解:
function rotate(arr) {
// 确定两个顶点
let a = 0
let b = 0
let x = arr.length - 1
let y = arr[0].length - 1
while (a < x && b < y) {
for (let i = 0; i < y - b; i++) {
const temp = arr[a][b+i]
arr[a][b+i] = arr[x-i][b]
arr[x-i][b] = arr[x][y-i]
arr[x][y-i] = arr[a+i][y]
arr[a+i][y] = temp
}
a++
b++
x--
y--
}
return arr
}
function zigzagPrint(arr) {
const res = []
// 确定两个顶点
let a = 0
let b = 0
let x = 0
let y = 0
let flag = true
while (a < arr.length && b < arr[0].length && x < arr.length && y < arr[0].length) {
printNode(a,b,x,y,flag)
flag = !flag
// 两个顶点移动轨迹
if (a < arr.length - 1) {
a++
} else if (b < arr[0].length - 1) {
b++
}
if (y < arr[0].length - 1) {
y++
} else if (x < arr.length) {
x++
}
}
return res
// 打印两点间的值
function printNode(a,b,x,y,flag) {
if (flag) {
while (a >= x) {
res.push(arr[a--][b++])
}
} else {
while (x <= a) {
res.push(arr[x++][y--])
}
}
}
}
function getMinTimes(N) {
// 假如N是一个质数
// 如果 m 变成2个a以上,即m = k 个 a。那么 s 最后一定会是 s = x * k * a 个数。这不符合N是质数的前提。
// 所以得出结论,当N是质数时,调用N-1次操作二是最优解
// 若N不是质数。把它分解为多个质数因子相乘的形式 N = x * y * z * o * p。
// 当操作到p时,p是一个质数,把(x * y * z * o)看作一个整体,那么最优解就是调用p-1次操作二。
// 那么由p推及到x。可以得出结论 res = x - 1 + y - 1 + z - 1 + o - 1 + p - 1。即 res = N的质数因子和 - N的质数因子个数
const { sum, num } = getPrimeFactor(N)
return sum - num
function getPrimeFactor(N) {
let sum = 0
let num = 0
for (let i = 2; i <= N;i++) {
while (N % i===0) {
sum += i
num++
N = N / i
}
}
return {
sum,
num
}
}
}
- 统计数组中字符串的词频。遍历词频表,把每条数据当成一个节点放入一个数组。实际上就是给这个数组按照词频做堆排序。取前K个最大的数。
function findKthLargest(nums, k) {
// 词频统计
const hashMap = new Map()
const help = []
for (let i of nums) {
hashMap.has(i) ? hashMap.set(i, hashMap.get(i) + 1) : hashMap.set(i, 1)
}
for (let i of hashMap.entries()) {
help.push({
key: i[0],
value: i[1]
})
}
nums = help
return heapSort(nums)
function heapSort(nums) {
let heapSize = 0
for (let i = 0; i<nums.length;i++) {
heapInsert(i)
heapSize += 1
}
while (k) {
[nums[0], nums[heapSize - 1]] = [nums[heapSize - 1], nums[0]]
heapSize -= 1
k -= 1
heapFy(0, heapSize)
}
function heapFy(i, heapSize) {
const leftIdx = 2 * i + 1
const rightIdx = leftIdx + 1
let target = i
if (leftIdx < heapSize && nums[leftIdx].value > nums[target].value) target = leftIdx
if (rightIdx < heapSize && nums[rightIdx].value > nums[target].value) target = rightIdx
if (target !== i) {
[nums[i], nums[target]] = [nums[target], nums[i]]
heapFy(target, heapSize)
}
}
function heapInsert(i) {
const father = Math.floor((i - 1) / 2)
if (nums[father]?.value < nums[i]?.value) {
[nums[father], nums[i]] = [nums[i], nums[father]];
i = father
heapInsert(i)
}
}
return nums.slice(heapSize)
}
};
// 复习时发现上述思路有误,更优解应该是创建一个小根堆。遍历数组生成词频表,当词频加一时,若小根堆的大小
//还没到k就直接加入这个字符信息,若小根堆已经到k个大小时,就跟小根堆堆顶元素比较,也就是说小根堆的堆顶就
//是一个瓶颈。超过这个瓶颈就是前K个最多的元素。