1两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。
对比两种方法感受:哈希表节约时间,花销空间
哈希表的主干:存储位置 = f(关键字),所以哈希表的时间复杂度就是常数阶O(1)。
var twoSum = function(nums, target) {
if(!nums) return [];
const m=new Map();
for(let i=0;i<nums.length;i++){
if(m.has(target-nums[i])){
return [m.get(target-nums[i]),i];
}
m.set(nums[i],i);
}
};
var twoSum = function(nums, target) {
if(!nums) return [];
for(let i=0;i<nums.length;i++){
for(let j=i+1;j<nums.length;j++){
if(nums[i]+nums[j]==target){
return [i,j];
}
}
}
return [];
};
2两数相加_链表操作
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
var addTwoNumbers = function(l1, l2) {
let head=null,tail=null;
let carry=0;
while(l1||l2){//length
const n1=l1?l1.val:0;
const n2=l2? l2.val:0;
//const n1=l1.val;长度较短的列表,cannot read the val of null
// const n2=l2.val;
if(!head){//once
head=tail=new ListNode((n1+n2+carry)%10);
}else{
tail.next=new ListNode((n1+n2+carry) %10);
tail=tail.next;
}
carry=Math.floor((n1+n2+carry)/10);
if(l1){
l1=l1.next;
}
if(l2){
l2=l2.next;
}
}
if(carry>0){
tail.next=new ListNode(carry);
}
return head;
};
3找出最长的无重复的子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
大循环内嵌小循环的结构体不太熟练
对比Map,Set是只能添加单一键值,用于查找
set去重
const m=new Set(nums);
let arr=Array.from(m);
var lengthOfLongestSubstring = function(s) {
if(!s) return 0;
const m=new Set();
let rk=-1,ans=0;
for(let i=0;i<s.length;i++){
if(i){//左指针向右移,移除字符
m.delete(s[i-1]);
}
while(rk+1<s.length&&!m.has(s[rk+1])){
m.add(s[rk+1]);
rk++;
}
ans=Math.max(ans,rk-i+1);
}
return ans;
};
4归并正序数组找中位数
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
示例 1:
输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2
var findMedianSortedArrays = function(nums1, nums2) {
for(let i=0;i<nums1.length;i++){//遍历nums1插入
if(nums1[i]>nums2[0]){
nums1.splice(i,0,nums2[0]);//插入
nums2.shift();//删除
}
}
if(!(nums2.length==0)){
nums1=nums1.concat(nums2);
}
if(nums1.length%2==0){
return(nums1[parseInt((nums1.length-1)/2)]+nums1[parseInt((nums1.length-1)/2)+1])/2;
}
else{
return nums1[(nums1.length-1)/2];
}
};
JavaScript数组
n.unshift(-2);//将-2插入数组首位
n.shift();//删除首位
n.splice(5,3);//删除三位:5、6、7
n.splice(5,0,2,3,4);//插入三位:5、6、7
n.splice(5,3,2,3,4);//替换三位:5、6、7
n.slice(start,end);//不影响原数组
n.pop();//删除末位
二维数组
printMatrix(averageTemp);//打印
数组迭代
every &
some |
for of
for (let n of nums1) {
console.log((n % 2 == 0) ? 'even' : 'odd');
}
forEach和箭头函数
numbers.forEach(function (x) {
console.log(x % 2 == 0);
});
//这段代码可以简化如下:
numbers.forEach(x => {
console.log((x % 2 == 0));
});
函数式编程
map
filter
reduce
5 中心扩展法找回文
枚举所有回文中心
var longestPalindrome = function(s) {
let maxLen=1,begin=0;
for(let i=0;i<s.length-1;i++){
let oddLen=isPalindrom2(s,i,i);//奇数回文串
let evenLen=isPalindrom2(s,i,i+1);
let theLen=Math.max(oddLen,evenLen);
if(theLen>maxLen){
maxLen=theLen;
begin=i-Math.floor((maxLen-1)/2);
}
}
return s.substr(begin,maxLen);
};
var isPalindrom2=function(str,left,right){
if(str[left]!=str[right]) return 1;
while(left>0&&right<str.length-1){
if(str[left]==str[right]){
left--;
right++;
}
else break;
}
if(str[left]!=str[right]){//加减循环一定要注意跳出循环的时候是否经历判断
left++;
right--;
}
return right-left+1;
}
6
var convert = function(s, numRows) {
if(numRows<2) return s;
let arr=[];
for(let i=0;i<s.length;i++){
const r=i%(2*numRows-2);
const index=r<numRows?r:2*numRows-2-r;
arr[index]=arr[index]?arr[index]+s[i]:s[i];//拼接二维数组
}
return arr.join('');
};
7整数反转
给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。
如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。
var reverse = function(x) {
let temp='',re;
if(x<0){//正值变换比较自由,所以先将符号隔离开
temp='-';
x=0-x;
}
console.log(typeof x);//number
re=(x+'').split("").reverse().join("");//number变字符串的两种方法
// re=x.toString().split("").reverse().join("");
if(Number(re)>=2**31&&x>0||Number(re)<2**31&&x<0){//幂操作数
return 0;
}else{
return temp + re;
}
};
9回文数
给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如,121 是回文,而 123 不是。
js提供了对数组的倒序,利用判断回文
其中
splite("")可以将字符串按某个字符分割,返回数组
如"hello".split(“e”) //[“h”,“llo”]
join是把数组拼接为字符串。
如 [“a”,“b”,“c”].join(",") //“a,b,c”
var isPalindrome = function(x) {
var str=x.toString();
if((str.split('').reverse().join('')==str)) return true;
else return false;
};
10正则表达式
var patt=new RegExp(pattern,modifiers);
或更简单的方法
var patt=/pattern/modifiers;
当使用构造函数创造正则对象时,需要常规的字符转义规则(在前面加反斜杠 \)。比如,以下是等价的:
var re = new RegExp("\\w+");
var re = /\w+/;
var isMatch = function(s, p) {
let reg=new ('^'+p+'$')//开头和结尾
return reg.test(s)
};
29两数相除(加法实现)
给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。
返回被除数 dividend 除以除数 divisor 得到的商。
整数除法的结果应当截去(truncate)其小数部分,例如:truncate(8.345) = 8 以及 truncate(-2.7335) = -2
初步思路:
每次加一做对比,结果超时
那要不每次加的数倍增,但是到后面过于危险
把判断和实际算次数分开,1、2、4、8加和判断,8、4、2、1算次数
var divide = function(dividend, divisor) {
// 获取符号
let a = dividend>=0,b = divisor>=0;//取符号
// 全部转正数处理
dividend = Math.abs(dividend)
divisor = Math.abs(divisor)
// 对除数进行翻倍 存储待用
// 最终 map = [...., [4,divisor*4] , [2,divisor*2] , [1,divisor*1]]
let c = 1;
let map = [];
let temp = divisor;
while(dividend >= temp){
map.unshift([c,temp]);//两倍增,[1,divisor]
temp += temp;
c += c;
}
// 让被除数不断减去map中小于它的除数 统计次数 则为结果
let sum = 0;
for(let i = 0;i< map.length && dividend > 0;i++){
let [c,divisor] = map[i]
if(dividend >= divisor){
dividend-=divisor;
sum +=c;
}
}
return a == b? Math.min(sum,2147483648-1):-Math.min(sum,2147483648);//取最小值来确定范围
};