目录
js实现千分位分隔符
function toThousands(num) {
var num = (num || 0).toString()
result = '';
while (num.length > 3) {
// 从末尾 3位3位 的截取并添加千分位分隔符
result = ',' + num.slice(-3) + result;
// slice返回的是一个新数组或字符串
num = num.slice(0, num.length - 3);
}
// num不足三位且存在时,进行拼接
if (num) { result = num + result; }
return result;
}
事实上,截取末尾三个字符的功能通过字符串类型的slice、substr或substring方法均可以做到嘻嘻😝。
正则表达式方式(这个我搞不定哪个大佬教教我):
function toThousands(num) {
return (num || 0).toString().replace(/(\d)(?=(?:\d{3})+$)/g, '$1,');
}
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
示例 1:
输入: "()"
输出: true
示例 2:
输入: "()[]{}"
输出: true
示例 3:
输入: "(]"
输出: false
示例 4:
输入: "([)]"
输出: false
示例 5:
输入: "{[]}"
输出: true
力扣20
解题思路:利用栈结构
将字符串中的字符依次入栈,遍历字符依次判断:
- 首先判断该元素是否是 { 、 ( 、 [ ,直接入栈
- 否则该字符为 } 、 ) 、 ] 中的一种,如果该字符串有效,则该元素应该与栈顶匹配,例如栈中元素有 ({, 如果继续遍历到的元素为 ), 那么当前元素序列为 ({) 是不可能有效的,所以此时与栈顶元素匹配失败,则直接返回 false ,字符串无效
当遍历完成时,所有已匹配的字符都已匹配出栈,如果此时栈为空,则字符串有效,如果栈不为空,说明字符串中还有未匹配的字符,字符串无效 。
var isValid = function(s) {
let map = {
'{': '}',
'(': ')',
'[': ']'
}
let stack = []
for(let i = 0; i < s.length ; i++) {
if(map[s[i]]) {
stack.push(s[i])
} else if(s[i] !== map[stack.pop()]){
return false
}
}
return stack.length === 0
};
这个思路真的好,代码也是我看了很多里面比较简洁易懂的,Salute!
数组中找出重复元素并排序
这是做的记不清哪家公司笔试中的题目了,数组中当然存放的不止是数字什么的,但是我想着既然能排序,应该就是数字了,忘记当时有没有这个限制。
function duplicateElement(arr) {
let temp = [];
arr.sort(function(a, b) {
return a - b;
}).sort(function(a, b) {
if(a == b && temp.indexOf(a) == -1) temp.push(a)
})
return temp;
}
字符串短横线和驼峰形式的互相转换
短横线转换为驼峰:
function charTohump (str) {
let arr = str.split('-');
let len =arr.length;
for (let i = 0;i < len;i++) {
arr[i] = arr[i].slice(0,1).toUpperCase()+arr[i].slice(1)
}
return arr.join('')
}
var a = charTohump('aa-bb-bsda-cdsa')
console.log(a); //AaBbBsdaCdsa
这样写存在一个问题,就是驼峰命名法分小驼峰和大驼峰,这样写会把首单词的第一个字母也变成大写,也就是所谓的大驼峰。
如下写法不会,其实主要还是看思想吧,这个无所谓,就是在驼峰转短横线的时候大驼峰小驼峰是有区别的。
function charTohump (str) {
//以-为分隔符进行分割
var arr = str.split('-');
str = arr.map((item,index) => {
if(index === 0){
return item;
}else {
return item.charAt(0).toUpperCase() + item.slice(1);
}
}).join('');
return str;
}
var a = charTohump('aa-bb-bsda-cdsa')
console.log(a); //aaBbBsdaCdsa
驼峰转换为短横线:
function humoTochar (str) {
//将字符串分割成字符串数组
var arr = str.split('');
str = arr.map((item) => {
//toUpperCase()将item转换成大写,不改变原来的item
if(item.toUpperCase() === item){
return '-'+item.toLowerCase();
}else{
return item;
}
}).join('');
return str;
}
正则的写法也应该是可以的,试了下没弄出来,后面弄出来了更新。
整数的阶乘,求尾数0的个数
function endZeors (n) {
// 其实就是找5的个数
if (n ===5 ) return 1
var count = 0;
while (n > 5) {
count += n/5;
n /= 5;
}
return count;
}
console.log(endZeors(25)) //5
console.log(endZeors(5)) //1
console.log(endZeors(125)) //30
只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
三种解题的思想:
1、利用indexOf()和lastIndexOf(),只要两个相等,就是只出现一次的数
/**
* @param {number[]} nums
* @return {number}
*/
var singleNumber = function(nums) {
var res = [];
var len = nums.length;
for(let i = 0;i < len;i++) {
if (nums.indexOf(nums[i]) === nums.lastIndexOf(nums[i]))
{
res.push(nums[i])
}
}
return res;
};
2、使用map记录下每个数的次数,占空间
var singleNumber = function(nums) {
const map = {},
res = [];
var len = nums.length;
for (let i = 0; i < len; i++) {
if (!map[nums[i]]) {
map[nums[i]] = 1;
} else {
map[nums[i]]++;
}
}
for (let i = 0; i < len; i++) {
if (map[nums[i]] === 1) {
res.push(nums[i]);
}
}
return res;
};
3、这种是比较推崇的写法,但是前提是需要了解异或运算。
需要运用异或运算的归零律、恒等律和结合律的知识。
/**
* @param {number[]} nums
* @return {number}
*/
var singleNumber = function(nums) {
var len = nums.length
for (var i = 1; i < len; i++) {
nums[0] = nums[0] ^ nums[i]; // 把所有的元素都异或到nums[0]上。
}
return nums[0];
};
两数之和
给出一个整数数组,请在数组中找出两个加起来等于目标值的数,
你给出的函数twoSum 需要返回这两个数字的下标(index1,index2),需要满足 index1 小于index2.。注意:下标是从1开始的
假设给出的数组中只存在唯一解
例如:
给出的数组为 {20, 70, 110, 150},目标值为90
输出 index1=1, index2=2
function twoSum( numbers , target ) {
// write code here
var len = numbers.length;
var map = new Map();
for (var i = 0;i < len;i++){
//如果map中含有这个减掉过后的值,其实就是这个属性,get这个属性就成了减掉后的i然后+1;
//然后本来的数也i+1;
//用数组输出这两个数即可
if(map.has(target - numbers[i])){
return [map.get(target - numbers[i])+1, i+1]
} else {
//不含有就从头到尾添加进map中
map.set (numbers[i], i)
}
}
}
搜索二维矩阵
编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:
- 每行中的整数从左到右按升序排列。
- 每行的第一个整数大于前一行的最后一个整数。
示例 1:
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
输出:true
示例 2:
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13
输出:false
提示:
- m == matrix.length
- n == matrix[i].length
- 1 <= m, n <= 100
- -104 <= matrix[i][j], target <= 104
这个方法通俗易懂:
var m = matrix.length;
function searchMatrix (matrix, target) {
for (var i = 0;i < m;i++) {
if(matrix[i].includes(target)) {
return true;
} else {
return false;
}
}
}
合并区间
以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi]
。请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间。
示例 1:
输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
示例 2:
输入:intervals = [[1,4],[4,5]]
输出:[[1,5]]
解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。
var merge = function (intervals) {
let res = [];
intervals.sort((a, b) => a[0] - b[0]);
let prev = intervals[0];
for (let i = 1; i < intervals.length; i++) {
let cur = intervals[i];
if (prev[1] >= cur[0]) { // 有重合
prev[1] = Math.max(cur[1], prev[1]);
} else { // 不重合,prev推入res数组
res.push(prev);
prev = cur; // 更新 prev
}
}
res.push(prev);
return res;
};
来源:leetdode
最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”。
示例 1:
输入:strs = ["flower","flow","flight"]
输出:"fl"
示例 2:
输入:strs = ["dog","racecar","car"]
输出:""
解释:输入不存在公共前缀。
取出数组的第一个字符串依次和剩余的字符串去比较。
function longestCommonPrefix (strs) {
if(!strs.length) return '';
let [a, ...b] = strs;
let result = '';
for(let i = 0; i < a.length; i++){
let flag = b.every(item => item[i] === a[i]);
if(flag) result += a[i];
else break;
}
return result;
}
来源:leetdode
最长不含重复字符的子字符串
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
我们首先来说说子串和子序列的区别吧,之前也碰到过很多次了,记录一下:
子串:原序列中必须连续的一段
子序列:原序列中可以不连续的一段
注意:无论是子串和子序列,元素的顺序都是原序列中的顺序
解题思路:
- 使用滑动窗口算法;
- 当遇到重复字符的时候删除重复字符前面(包括这个重复字符)的所有字符;
- 记录达到不重复的最长子字符长度;
- 循坏之后有更长的不重复子串就更新我们的不重复最大子字符串长度;
function lengthOfLongestSubstring( s ) {
// write code here
let str = [],
maxlen = 0 ,
len = s.length;
for (let i = 0;i < len;i++) {
let index = str.indexOf(s[i]);
if(index != -1) {
str.splice(0, index+1);
}
str.push(s[i]);
maxlen = Math.max(maxlen, str.length);
}
return maxlen;
}