剑指offer -javascript版本
✔1.二维数组的查找
-
题目描述:在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
-
解答方法:
-
力扣 成功 暴力解法——自己想到的解法
-
思路:两层for遍历,如果目标值与遍历的某个值相等,则返回true
-
代码:
function Find(target, array)
{
const rowNum = array.length
if(!rowNum){
return false
}
const colNum = array[0].length
if(!colNum){
return false
}
for(let i=0;i<rowNum;i++){
for(let j=0;j<colNum;j++){
if(target === array[i][j]){
return true
}
}
}
return false
} -
时间复杂度:O(N^2),空间复杂度:O(1)
-
-
力扣提交失败 观察数组规律(最优)
-
思路:数组的特点是每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。考虑以下数组:
1 2 3
4 5 6
7 8 9在其中寻找 5 是否存在。过程如下:
-
从右上角开始遍历
-
目标元素大于当前元素( 5 > 3),根据数组特点,当前行中最大元素也小于目标元素,因此进入下一行
-
目标元素小于当前元素( 5 < 6),根据数组特点,行数不变,尝试向前一列查找
-
找到 5
-
-
代码:
function Find(target, array)
{
const rowNum = array.length
if(!rowNum){
return false
}
const colNum = array[0].length
if(!colNum){
return false
}
let row = 0,
col = colNum - 1
while(row < rowNum && col >= 0){
if(array[row][col] === target){
return true
}else if(target > array[row][col]){
row++
}else{
col--
}
}
}
var findNumberIn2DArray = function(matrix, target) {
let rowNum = matrix.length
if(!rowNum) return false
let colNum =matrix[0].length
if(!colNum) return false
let row=0
let col=colNum-1
while(row<rowNum&&col>=0){
if(target==matrix[row][col]){
return true
} else if (target<matrix[row][col]){
col--
} else{
row++
}
}
}; -
时间复杂度是 O(M+N),空间复杂度是 O(1)。其中 M 和 N 分别代表行数和列数。
-
-
✔2.调整数组顺序使奇数位于偶数前面
-
题目描述:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
-
解答方法:
-
方法一——自己想到的解法
-
思路:遍历数组,判断遍历的每个值是奇数还是偶数,如果是奇数push到一个新建的左侧数组里,如果是偶数push到一个新建的右侧数组里,最后合并左右侧数组,返回即可
-
代码:
function reOrderArray(array)
{
// write code here
const len = array.length
if(!len){
return false
}
const left_temp = []
const right_temp = []
for(let i=0;i<len;i++){
//奇数
if(array[i]%2===1){
left_temp.push(array[i])
}else{
//偶数
right_temp.push(array[i])
}
}
array = left_temp.concat(right_temp)
return array
} -
时间复杂度:O(N),空间复杂度:O(N)
-
-
方法二——自己想到的解法
-
思路:采用插入排序的思想实现
-
代码:
function reOrderArray(array)
{
let k = 0 //记录已经摆好位置的奇数的个数
for(let i=0;i<array.length;i++){
if(array[i]%2===1){
let j = i
while(j>k){
let temp = array[j]
array[j] = array[j-1]
array[j-1] = temp
j--
}
k++
}
}
return array
} -
时间复杂度:O(N^2),空间复杂度:O(1)
-
-
方法三——yfh自创 时间复杂度:O(N),空间复杂度:O(N)
-
代码
var exchange = function(nums) {
let res=[]
for(let i=0;i<nums.length;i++){
if (nums[i]%2==0){
res.push(nums[i])
} else{
res.unshift(nums[i])
}
}
return res
};
-
-
✔3.把数组排成最小的数
-
题目描述:输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
-
解答方法:
-
思路:借助自定义排序,可以快速比较两个数的大小。比如只看[3, 32]这两个数字。它们可以拼接成 332 和 323,按照题目要求,这里应该取 323。
-
代码:
字符串 xy < yx , yz < zy ,需证明 xz < zx 一定成立。
设十进制数 x, y, z 分别有 a, b, c 位,则有:
(左边是字符串拼接,右边是十进制数计算,两者等价)
xy = x * 10^b + y
yx = y * 10^a + x
则 xy < yx 可转化为:
x * 10^b + y < y * 10^a + x
x (10^b - 1) < y (10^a - 1)
x / (10^a - 1) < y / (10^b - 1) ①
同理, 可将 yz < zy 转化为:
y / (10^b - 1) < z / (10^c - 1) ②
将 ① ② 合并,整理得:
x / (10^a - 1) < y / (10^b - 1) < z / (10^c - 1)
x / (10^a - 1) < z / (10^c - 1)
x (10^c - 1) < z (10^a - 1)
x * 10^c + z < z * 10^a + x
∴ 可推出 xz < zx ,传递性证毕
function PrintMinNumber(numbers)
{
const len = numbers.length
if(!len){
return ""
}
numbers.sort((x,y) => {
-