记录一道算法题
煎饼排序
969. 煎饼排序 - 力扣(LeetCode) (leetcode-cn.com)
要求:
* 每次从 0 到 n 进行翻转
* 数组是从 1 到 n 的升序数组进行打乱之后的数组
* 用数组记录每次翻转的个数,直到恢复升序排列
看了给的例子并没有发现什么规律,官方给的例子是
输入:[3,2,4,1]
输出:[4,2,4,3]
解释:
我们执行 4 次煎饼翻转,k 值分别为 4,2,4,和 3。
初始状态 arr = [3, 2, 4, 1]
第一次翻转后(k = 4):arr = [1, 4, 2, 3]
第二次翻转后(k = 2):arr = [4, 1, 2, 3]
第三次翻转后(k = 4):arr = [3, 2, 1, 4]
第四次翻转后(k = 3):arr = [1, 2, 3, 4],此时已完成排序。
完全没看出有什么规律,但如果数组是升序的就不需要进行翻转,输出的结果是 [],
然后第二次翻转其实提供了灵感,当最大的数在第一个位置的时候,这时候整体翻转整个数组,就可以得到 [3, 2, 1, 4], 这时候已经把一个数归位了。然后下次就是再整体翻转的时候就是 arr.length - 1,以此类推。
- 首先找到最大的数字的下标,如果不是在最后一位就进行翻转,如果是就直接下一轮查找
- 如果找到了是在第1位,直接翻转整个数组,如果在其他位置就翻转相关的个数。
function reverse(arr, count) {
// 根据个数算出中间的位置
let k = count % 2 === 0 ? count / 2 : count >> 1
for(let i = 0; i < k; i++) {
const temp = arr[i]
arr[i] = arr[count - 1 - i]
arr[count- 1 - i] = temp
}
}
function pancakeSort(arr) {
let result = []
let n = arr.length
while(n > 1) {
// 只要确定 length - 1 个的位置正确就可以,所以少一个
let i = 0
// n是还未确定的个数,后续会递减 相当于 [1, 3, 1, 4],就不用遍历全部数组
for(; i < n; i++) {
if(arr[i] === n) {
break
// 因为是升序所以刚好 n 等于未确定位置的最大数
}
}
if (i === n) {
// 找完一轮,如果最大的数在正确的位置就不用翻转
n--
continue
}
if (i === 0) {
// 第一个就翻转全部, 这时有一个数会被正确归位
reverse(arr, n)
result.push(n)
n--
} else {
reverse(arr, i + 1)
result.push(i + 1)
}
}
return result
}
以上并不是次数最少的方法。但是也能做出来。不知道官方给的例子是怎么算出来的,只要4次翻转。