🎈 算法并不一定都是很难的题目,也有很多只是一些代码技巧,多进行一些算法题目的练习,可以帮助我们开阔解题思路,提升我们的逻辑思维能力,也可以将一些算法思维结合到业务代码的编写思考中。简而言之,平时进行的算法习题练习带给我们的好处一定是不少的,所以让我们一起来养成算法练习的习惯。今天练习的题目是一道比较简单的题目 ->半有序排列
问题描述
给你一个下标从 0 开始、长度为 n 的整数排列 nums 。
如果排列的第一个数字等于 1 且最后一个数字等于 n ,则称其为 半有序排列 。你可以执行多次下述操作,直到将 nums 变成一个 半有序排列 :
- 选择
nums中相邻的两个元素,然后交换它们。
返回使 nums 变成 半有序排列 所需的最小操作次数。
排列 是一个长度为 n 的整数序列,其中包含从 1 到 n 的每个数字恰好一次。
示例 1:
输入: nums = [2,1,4,3]
输出: 2
解释: 可以依次执行下述操作得到半有序排列:
1 - 交换下标 0 和下标 1 对应元素。排列变为 [1,2,4,3] 。
2 - 交换下标 2 和下标 3 对应元素。排列变为 [1,2,3,4] 。
可以证明,要让 nums 成为半有序排列,不存在执行操作少于 2 次的方案。
示例 2:
输入: nums = [2,4,1,3]
输出: 3
解释: 可以依次执行下述操作得到半有序排列:
1 - 交换下标 1 和下标 2 对应元素。排列变为 [2,1,4,3] 。
2 - 交换下标 0 和下标 1 对应元素。排列变为 [1,2,4,3] 。
3 - 交换下标 2 和下标 3 对应元素。排列变为 [1,2,3,4] 。
可以证明,要让 nums 成为半有序排列,不存在执行操作少于 3 次的方案。
示例 3:
输入: nums = [1,3,4,2,5]
输出: 0
解释: 这个排列已经是一个半有序排列,无需执行任何操作。
提示:
2 <= nums.length == n <= 501 <= nums[i] <= 50nums是一个 排列
思路分析
首先我们应该要先理解一下题目意思,题目会给我们一个数组nums,我们需要对其进行排列,使其成为半有序排列 ,那么什么是半有序排列 呢?半有序排列 在这里的定义是:
- 如果排列的第一个数字等于
1且最后一个数字等于n,则称其为 半有序排列 。
数组nums 是一个长度为 n 的整数序列,其中包含从 1 到 n 的每个数字恰好一次,所以我们不需要考虑出现多个相同字符的情况。
我们每次操作可以选择 nums 中相邻的两个元素,然后交换它们,所以我们需要执行操作的次数其实就取决于元素1和元素n的初始下标,所以我们可以先找到元素1和元素n的初始下标,之后再分别计算元素1和元素n需要移动的距离:元素1需要移动到数组第一位,其需要移动的距离即为其初始下标加1;元素n需要移动到数组的最后一位,其需要移动的距离为数组长度 - 其初始下标。
这里需要注意一种情况,元素1位于元素n的右方,这种情况下会有一次交换是元素1和元素n之间进行交换,这时候总交换次数需要减去一次:
AC 代码
完整 AC 代码如下:
/**
* @param {number[]} nums
* @return {number}
*/
var semiOrderedPermutation = function (nums) {
let ind1 = 0,
ind2 = 0;
for (let i = 0; i < nums.length; i++) {
if (nums[i] === 1) ind1 = i;
if (nums[i] === nums.length) ind2 = i;
}
return ind1 + (nums.length - ind2 - 1) - (ind1 > ind2 ? 1 : 0);
};
说在后面
🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,在此谢谢大家的支持,我们下文再见 🙌。