前端程序员学好算法系列(一)数组
前端程序员怎么才能学好算法呢?目前算法优秀的视频集中在c++,java,python,本人通过几个月专心看c++的视频掌握了算法的基本思路,都翻译成前端代码一一写出来,从真题到思维全面提升算法思维
面对算法面试,不畏惧
二分查找法O(logn)
寻找数组中的最大/最小值O(N)
归并排序算法 O(nlogn)
选择排序算法O(n^2)
第一题.数组 704.二分查找法
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
示例 1:
输入: nums = [-1,0,3,5,9,12], target = 9 输出: 4 解释: 9 出现在 nums 中并且下标为 4
解题:
1.在左边界0 和右边界arr.length -1 中进行寻找,
2.每次取最中间的元素mid,如果当前寻找的元素就是当前元素直接返回,
3.否则当前元素小于target左边界等于mid+1 否则右边界等于mid -1,如果没有找到返回-1
function binarySearch(arr,target) { let l = 0 let r = arr.length - 1 let mid while(l<=r){ // mid = Math.floor((l + r)/2) // 下面的代码解决l+r 整数溢出的问题 mid = Math.floor(l + (r-l)/2) if(arr[mid]===target){ return mid } if(arr[mid] < target){ l = mid + 1 } else { r = mid - 1 } } return -1 }
第二题283. 移动零
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
示例:
输入: [0,1,0,3,12] 输出: [1,3,12,0,0]
说明:
必须在原数组上操作,不能拷贝额外的数组。
尽量减少操作次数。
解题:
1.我们定义一个k指针默认为0
2.循环数组当数组值为0时交换数组k和当前索引的值k++
3.如果 i!=k 这步针对特殊用力优化
var moveZeroes = function(nums) { let k = 0 for(let i =0;i<nums.length;i++){ if(nums[i]){ if(i!=k){ swap(nums,k,i) k++ } else { k++ } } } function swap(arr,i,j){ let tmp = arr[i] arr[i] = arr[j] arr[j] = tmp } };
第三题 27.移动元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
示例 1:
给定 nums = [3,2,2,3], val = 3, 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 你不需要考虑数组中超出新长度后面的元素。
解题:此题原理与上题相同
var removeElement = function(nums, val) { let j = 0 let arr =[] for(let i =0,len=nums.length;i<len;i++){ if(nums[i]!==val){ nums[j] = nums[i] j++ } } return j };
第四题 75. 颜色分类
给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
注意:
不能使用代码库中的排序函数来解决这道题。
示例:
输入: [2,0,2,1,1,0] 输出: [0,0,1,1,2,2]
解题一
暴力解法:
1.本题只有三种颜色所以我们可以给统计每个元素出现的次数保存起来然后在按数量值依次排列,代码如下
var sortColors = function(nums) { let obj = {} for(let i =0;i<nums.length;i++){ if(!obj[nums[i]]){ obj[nums[i]] = 1 } else { obj[nums[i]] = obj[nums[i]] + 1 } } let index = 0 for(let i=0;i<obj[0];i++){ nums[index++] = 0 } for(let i=0;i<obj[1];i++){ nums[index++] = 1 } for(let i=0;i<obj[2];i++){ nums[index++] = 2 } };
解法二
三路快排
1.定义前边界zero为-1,因为默认左边界中没有任何一个元素,左边界内存放所有为0的元素
2. 定义右边界tow后面的元素都是2,tow中默认也不存在任何元素
3.我们这里for循环时没有i++ 因为我们需要处理一种不需要i++的情况,当当前愿随num[i] ==2时我们把 tow-- 然后tow和i交换位置,此时i位置的元素为tow位置交换过去的元素,还为访问,所以i不需要++
var sortColors = function(nums) { let zero = -1 // nums[0...zero] ==0 let tow = nums.length // nums[tow..n-1] ==2 for(let i =0;i<tow;){ if(nums[i]===1){ i++ } else if(nums[i] ==2){ --tow swap(nums,i,tow) } else { zero++ swap(nums,i,zero) i++ } } function swap(arr,i,j){ let tmp =arr[i] arr[i] = arr[j] arr[j] = tmp } };
算法数组入门暂时就先写到这里