01- 单链表的排序
描述
给定一个节点数为n的无序单链表,对其按升序排序。
示例1
输入:[1,3,2,4,5]
返回值:{1,2,3,4,5}
思路:辅助数组,将原链表中的数据取出来放在一个新数组中,然后对这个数组进行排序,排序之后再将数组中的有序数据按照顺序插入链表中。
代码实现:
function sortInList( head ) {
// write code here
if(head == null) return head
let numArr = []
let node = head
while(node){
numArr.push(node.val)
node = node.next
}
if(numArr.length === 1) return head
numArr.sort((a , b) => a - b)
let newHead = {
val : numArr[0],
next : null
}
let node2 = newHead
for(let i = 1 ; i < numArr.length; i ++){
let newNode = {
val : numArr[i],
next : null
}
node2.next = newNode;
node2 = node2.next
}
return newHead
}
02- 旋转数组的最小数字
有一个长度为 n 的非降序数组,比如[1,2,3,4,5],将它进行旋转,即把一个数组最开始的若干个元素搬到数组的末尾,变成一个旋转数组,比如变成了[3,4,5,1,2],或者[4,5,1,2,3]这样的。请问,给定这样一个旋转数组,求数组中的最小值。
示例1
输入:[3,4,5,1,2]
返回值:1
思路:二分法
1.一个mid =(left + right)/2变量取数组区间的中间位置(向下取整)
2.比较这个中间值和最右边值的大小arr[mid] > arr[right]则缩减为mid后半部分 left = mid + 1 如果arr[mid] < arr[right] right = mid
(这里为什么总是和右边的数据比较大小? 原因是在数组旋转之前是升序数组,将数组前面若干数据放到元素组尾部之后,最右边的值就相当于是一个基准值,它前面可能存在有连续比它小的数据,也有可能自己就是最小。相较于中间mid位置的值来说如果大于arr[right]就说明当前这个元素在原始数组中时在arr[right]后面的,所以这个时候可以确定最小值肯定在[mid + 1, right]这个区间内。如果arr[mid] < arr[right] 则说明数组旋转的程度很大,将一半以上长度的数据旋转到了尾部,那此时说明arr[mid]这个值本来就是arr[right]左边的数据,所以最小值有可能就是arr[mid]自己本身或者前面的某一个值。所以缩减区间为[left,mid]) right = mid。
3.如果arr[mid] == arr[right] right -- 就从右边开始缩减整个数组的范围然后重新计算mid的值,重复上述两步操作
4. i === j 退出循环,返回arr[i]即可
代码实现:
function minNumberInRotateArray(rotateArray)
{
// write code here
if(rotateArray.length === 0) return 0
let left = 0 , right = rotateArray.length - 1
while(left < right){
let mid = Math.floor((left + right) / 2)
if(rotateArray[mid] > rotateArray[right]) left = mid + 1
else if(rotateArray[mid] < rotateArray[right]) right = mid
else right --
}
return rotateArray[left]
}
03 - 二叉树的镜像
描述
操作给定的二叉树,将其变换为源二叉树的镜像。
思路:自底向上(递归):将每一个节点的左右孩子进行一个交换,一直到将根节点的两颗左右子树的交换,就可以生成原树的镜像
代码实现:
function Mirror( pRoot ) {
// write code here
if(pRoot == null) return pRoot
function recursive(node){
if(node == null) return
recursive(node.left)
recursive(node.right)
let temp = node.left
node.left = node.right
node.right = temp
}
recursive(pRoot)
return pRoot
}
04 - 数组中出现次数超过一半的数字
给一个长度为 n 的数组,数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
例如输入一个长度为9的数组[1,2,3,2,2,2,5,4,2]。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。
示例1
输入:[1,2,3,2,2,2,5,4,2]
返回值:2
思路:
1.将原数组去重得到一个新数组newArr
2.根据新数组的长度,在常见出一个次数数组numCounts
3.循环新数组中的数据比较其在原数组出现的次数,将次数分别放在元素对应下标的数组中
4.找到次数数组numCounts中最大的值,获取它的下标,通过下标将新数组中对应的数字返回即可
代码实现:
function MoreThanHalfNum_Solution(numbers)
{
// write code here
let newArr = [...new Set(numbers)]
let numCounts = new Array(newArr.length)
for(let i = 0 ; i < newArr.length; i ++){
numCounts[i] = 0
for(let j = 0; j < numbers.length; j ++){
if(newArr[i] === numbers[j]){
numCounts[i] ++
}
}
}
let max = Math.max.apply(null,numCounts)
let index = numCounts.indexOf(max)
return newArr[index]
}
05 - 数字在升序数组中出现的次数
描述
给定一个长度为 n 的非降序数组和一个非负数整数 k ,要求统计 k 在数组中出现的次数
示例1
输入:[1,2,3,3,3,3,4,5],3
返回值:4
思路:双指针夹逼,left指针向右边指,right指针向左边指,最终符合条件了,返回left + right + 1即可
function GetNumberOfK(data, k)
{
// write code here
if(data[data.length - 1] < k) return 0
let left = 0
let right = data.length - 1
while(left < right){
// 这里要做限制,防止left指针一直++ 形成死循环
while(data[left] != k && left <= right) left ++
// 这里也是一样
while(data[right] != k && right >= left) right --
return right - left + 1
}
if(data[left] === k) return 1
else return 0
}
06 -用两个栈实现队列
描述:
用两个栈来实现一个队列,使用n个元素来完成 n 次在队列尾部插入整数(push)和n次在队列头部删除整数(pop)的功能。 队列中的元素为int类型。保证操作合法,即保证pop操作时队列内已有元素。
思路:
1.栈结构先进后出,队列先进先出,所以两个栈一个作为压入数据的栈stakc1,一个作为弹出数据的栈stack2。stack2中的数据必须是从stack1中弹栈又重新压入stack2中的。
2.弹栈操作时,必须将现有栈stack2中的的数据全部弹完再去stack1中重新去数据
代码实现:
let stack1 = [] // 押入栈
let stack2 = [] // 输出栈
function push(node)
{
// write code here
stack1.push(node)
}
function pop()
{
// write code here
// 栈中有数据就直接弹出
if(stack2.length) return stack2.pop()
else {
// 如果输出栈stack2中没有数据的时候才去押入栈中去拿
if(stack1.length){
while(stack1.length != 0){
stack2.push(stack1.pop())
}
return stack2.pop()
}else{
// 如果压入栈也没有数据,就表示队列里面没有数据 直接返回null
return null
}
}
}
07 - 调整数组顺序使奇数位于偶数前面
描述
输入一个长度为 n 整数数组,数组里面不含有相同的元素,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前面部分,所有的偶数位于数组的后面部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
示例1
输入:[1,2,3,4]
返回值:[1,3,2,4]
思路:
1.一个存储全部元素的新数组newArr,将偶数按照顺序push到数组里面
2.一个保存前面奇数的数组prevArr,按照奇数本身原有的次序push到prevArr中
3.将prevArr数据展开放到,newArr的头部
代码实现:
function reOrderArray( array ) {
// write code here
let newArr = []
let prevArr = []
for(let i = 0 ; i < array.length; i ++){
if(array[i] % 2 === 0){
newArr.push(array[i])
}else{
prevArr.push(array[i])
}
}
newArr.unshift(...prevArr)
return newArr
}