js實用算法

判斷文本是否為回文

定義:如果將一個文本翻轉過來,能和原文本完全相等,那么就可以稱之為“回文”。

方法一(字符串、數組內置方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
* 判斷文字是否為回文
* @param {string|number} val 需要判斷的文字
* @return {boolean} bool 是否為回文
*/
function isPalindrome1(val){
// 允許輸入字符串和數字和布爾值
if (typeof val !== 'string') val = val.toString();
let newVal = val.split('').reverse().join('');
return val === newVal;
}
isPalindrome1(121) // true
isPalindrome1('yuzuy') // true

// PS:方法簡單,但效率不高,會產生一個新的變量

方法二(循環)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
* 判斷文字是否為回文
* @param {string|number} val 需要判斷的文字
* @return {boolean} bool 是否為回文
*/
function isPalindrome2(val){
val = val + ''; // 非字符串轉化為字符串
// 這里為什么 i <= j 呢?如果中間只有一個字符,是不需要比較的,它肯定等于它本身!!!
for(let i = 0, j = val.length - 1; i < j; i++, j--){
if(val.charAt(i) !== val.charAt(j)){
return false;
}
}
return true;
}
isPalindrome2(121) // true
isPalindrome2('yuzuy') // true

PS:網上還有其他解法,大多為以上兩種的變形。

反轉字符串

方法一(字符串、數組內置方法))

借用反轉字符串的方法

1
2
3
4
5
6
7
8
9
10
/*
* 反轉字符串
* @param {string} val 需要反轉的字符串
* @return {string} str 反轉后的字符串
*/
function reverseVal1(val){
if (typeof val !== 'string') return;
return val.split('').reverse().join('');
}

方法二(循環)

循環系列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*
* 反轉字符串
* @param {string} val 需要反轉的字符串
* @return {string} str 反轉后的字符串
*/
function reverseVal2(val){
if (typeof val !== 'string') return;
let str = '',
i = 0,
len = val.length;
while(i < len){
str += val.charAt(len - 1 - i);
i++;
}
return str;
}
/*
* 反轉字符串
* @param {string} val 需要反轉的字符串
* @return {string} str 反轉后的字符串
*/
function reverseVal3(val){
if (typeof val !== 'string') return;
let str = '',
len = val.length;
for(let i = len - 1; i >= 0; i--){
str += val.charAt(i)
}
return str;
}

測試:reverseVal(‘abc’) // ‘cba’

階乘

方法一(遞歸)

1
2
3
4
5
6
7
8
9
10
11
12
/*
* 階乘
* @param {number} n 需要求的階乘
* @return {number} 階乘值
*/
function factorialize1(n){
if(typeof n !== 'number') throw new Error('參數必須為整整')
if(n === 1) return 1;
// 建議不要使用 arguments.callee,目前已經廢棄了。
return n * factorialize1(n - 1);
}

PS:上面代碼是一個階乘函數,計算n的階乘,最多需要保存n個調用記錄,復雜度 O(n) 。
遞歸非常耗費內存,因為需要同時保存成千上百個調用幀,很容易發生“棧溢出”錯誤(stack overflow)。

方法二(ES6尾調用優化)

(遞歸優化版)

1
2
3
4
5
6
7
8
9
10
11
12
/*
* 階乘
* @param {number} n 需要求的階乘
* @return {number} 階乘值
*/
function factorialize2(n, total = 1){
if(typeof n !== 'number' || typeof total !== 'number') throw new Error('參數必須為整整')
if(n === 1) return total;
return factorialize2(n - 1, n * total)
// f(3) => f(2, 3 * 2) => f(1, 6) => 6
}

PS:ES6尾調用優化但對于尾遞歸來說,由于只存在一個調用幀,所以永遠不會發生“棧溢出”錯誤。
尾調用(Tail Call)是函數式編程的一個重要概念,本身非常簡單,一句話就能說清楚,就是指某個函數的最后一步是調用另一個函數。

方法三(循環)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
* 階乘
* @param {number} n 需要求的階乘
* @return {number} 階乘值
*/
function factorialize3(n){
if(typeof n !== 'number') throw new Error('參數必須為整整')
if(n === 1) return 1;
let total = 1;
while(n>1){
total = n * total;
n--;
}
return total;
}

測試:factorialize1(3) // 6

隨機生成長度為n字符串

方法一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
* 生成指定長度的隨機字符串
* @param {number} n 生成字符串個數
* @return {string} str 反轉后的字符串
*/
function randomString1(n){
let str = 'abcdefghijklmnopqrstuvwxyz0123456789';
let tem = '',
i = 0;
// Math.random 函數產生值的范圍[0,1)
while(i<n){
tem += str.charAt(Math.floor(Math.random() * str.length))
i++;
}
return tem;
}

PS:Math.round(Math.random()?(str.length - 1))
Math.ceil(Math.random()?
(str.length - 1))
Math.floor(Math.random() * str.length)
這三種方式等價,都能生成[0, str.length-1]隨機數

方法二(進制轉化)

1
2
3
4
5
6
7
8
/*
* 生成指定長度的隨機字符串
* @param {number} n 生成字符串個數
* @return {string} 反轉后的字符串
*/
function randomString2(n){
return Math.random().toString(36).substr(2).slice(0, n)
}

PS:該方法原理為隨機產生的數轉換為指定進制字符串
toString(n),n為[2,36],n<=10時只產生0-9也就是10進制數字
該方法有個缺點,產生字符串的長度有一定的限制。

方法三(隨機碼點)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
* 生成指定長度的隨機字符串
* @param {number} n 生成字符串個數
* @return {string} str 反轉后的字符串
*/
function randomString3(n){
let str = '';
function randomChar(){
let l = Math.floor(Math.random() * 62);
if(l < 10) return l; // 數字部分 0-9
if(l < 36) return String.fromCharCode(l + 55); // 大寫字母
return String.fromCharCode(l + 61); // 小寫字母
}
while(str.length < n) str += randomChar();
return str;
}

PS:可以參考對于的ASCII碼表。
測試:randomString1(3) // ‘1sd’

數組去重

方法一(ES6的Set數據結構)

1
2
3
4
5
6
7
8
/*
* 數組去重
* @param {array} ary 需要去重的數組
* @return {array} 去重后的數組
*/
function unique1(ary){
return [...new Set(ary)];
}

方法二(對象的key唯一性)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
* 數組去重
* @param {array} ary 需要去重的數組
* @return {array} 去重后的數組
*/
function unique2(ary){
let obj = {},
i = 0,
len = ary.length;
while(i < len){
if(!obj[ary[i]]){
obj[ary[i]] = true; // 如果不存在
}
i++;
}
return Object.keys(obj);
}

PS:該方法存在一定問題,數組的元素全部被轉化為字符串,因為ES6之前對象的key只能是字符串。
會把數字1和字符串’1’,會被視為同一個值。

方法三(臨時數組判斷插入)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
* 數組去重
* @param {array} ary 需要去重的數組
* @return {array} 去重后的數組
*/
function unique3(ary){
let tem = [],
i = 0,
len = ary.length;
while(i < len){
// tem.indexOf() === -1 同理
!tem.includes(ary[i]) ? tem.push(ary[i]) : '';
i++;
}
return tem;
}

方法四(判斷首次出現的位置)

如果當前數組的第i項在當前數組中第一次出現的位置不是i,那么表示第i項是重復的,忽略掉。否則存入結果數組。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*
* 數組去重
* @param {array} ary 需要去重的數組
* @return {array} 去重后的數組
*/
function unique4(ary){
let tem = [ary[0]],
len = ary.length;
for(let i = 1; i < len; i++ ){
// 核心,首次的索引出現是否為當前的索引
if(ary.indexOf(ary[i]) === i) tem.push(ary[i]);
}
return tem;
}

方法五(排序后逐個比較插入)

給傳入數組排序,排序后相同值相鄰,然后遍歷時新數組只加入不與前一值重復的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
* 數組去重
* @param {array} array 需要去重的數組
* @return {array} 去重后的數組
*/
function unique5(array){
let ary = array.slice();
ary.sort();
let tem = [ary[0]];
for(let i = 0, len = ary.length; i < len; i++){
ary[i] !== tem[tem.length - 1] ? tem.push(ary[i]) : '';
}
return tem;
}

PS:返回的數組順序發生了改變。

方法六()

獲取沒有重復的最右一值放入新數組(檢測到有重復值時終止當前循環同時進入頂層循環的下一輪判斷)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*
* 數組去重
* @param {array} ary 需要去重的數組
* @return {array} 去重后的數組
*/
function unique6(ary){
let tem = [];
for(let i = 0, len = ary.length; i < len; i++){
for(let j = i + 1; j < len; j++){
if(ary[i] === ary[j]) j = ++i;
}
tem.push(ary[i])
}
return tem;
}

測試:unique1([1, 2, 3, 2]) // [1, 2, 3]

出現次數最多的字符

方法一(對象key的唯一性進行累加)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function maxNum1(str){
if(typeof(str) !== 'string') str = str.toString();
let obj = {},
maxChar = []; // 使用數組保存出現最多次的某些字符
str.split('').forEach( (val) => {
if(!obj[val]){
let demo = obj[val] = 1;
}else{
obj[val]++;
}
})
let maxCount = Math.max.apply(null, Object.values(obj))
// forEach方法總是返回 undefined 且 沒有辦法中止或者跳出 forEach 循環。
Object.entries(obj).forEach( item => {
if(item[1] == maxCount){
maxChar.push(item[0])
}
})
return maxChar;
}

測試:maxNum1(‘11223333’) // ‘3’

數組扁平化

實現方法:Array.prototype.flatten(depth),參數depth表示需要扁平化的層數,返回一個新的數組。

方法一(遞歸遍歷數組拼接)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function flatten1(ary){
let tem = [],
i = 0,
len = ary.length;
while(i < len){
if(Array.isArray(ary[i])){
// 遞歸進行上面步驟
// [].concat(...ary),它的參數可以為數組或值,作用為將數組或值連接成新數組。
tem = tem.concat(flatten1(ary[i]))
}else{
tem.push(ary[i]);
}
i++;
}
return tem;
}

PS:可以處理多層數組。

方法二(reduce結合concat)

1
2
3
4
5
6
7
function flatten2(ary){
return ary.reduce((pre, cur) => {
return pre.concat(Array.isArray(cur) ? flatten2(cur) : cur)
}, [])
}

PS:可以處理多層數組。

方法三(轉化為字符串)

1
2
3
4
5
function flatten2(ary){
return ary.toString().split(',')
}

PS:返回的數組項將為字符串。

方法四(解構數組)

1
2
3
4
5
6
7
8
9
10
11
12
13
function flatten4(ary){
let tem = []
ary.forEach(item => {
if(Array.isArray(item)){
tem = tem.concat(...item);
}else{
tem = tem.concat(item);
}
})
return tem;
}

PS:只能處理2維數組。
測試:getMaxProfit1([1, 2, 3, [4, 5, 6]]) // [1, 2, 3, 4, 5, 6]

數組中最大差值

方法一

1
2
3
function getMaxProfit1(ary){
return Math.max.apply(null, ary) - Math.min.apply(null, ary);
}

測試:getMaxProfit1([1, 2, 3, 4]) // 3

斐波那契數列

這里我們只實現通項公式

方法一

1
2
3
4
5
6
7
function fib1(n){
if(n === 1 || n === 2){
return 1;
}
return fib1(n - 1) + fib1(n - 2);
}

PS:時間復雜度為O(2^n),空間復雜度為O(n)

方法二

1
2
3
4
5
6
7
8
9
10
11
12
13
function fib2(n){
let tem = [1, 1];
if(n === 1 || n === 2){
return 1;
}
// 數組索引從0開始,數列索引從1開始
for(let i = 2; i < n; i++){
tem[i] = tem[i-1] + tem[i-2];
}
return tem[n-1];
}

PS:時間復雜度為O(n),空間復雜度為O(n)

方法三

1
2
3
4
5
6
7
8
9
10
11
12
function fib2(n){
let prev = 1,
next = 1,
res;
for(let i = 2; i < n; i++){
res = prev + next;
prev = next;
next = res;
}
return res;
}

PS:時間復雜度為O(n),空間復雜度為O(1)
測試:fib2(3) // 2

判斷是否為質數(prime number)素數

質數:只能被1和自己整除且大于1的數。
合數:數大于1且因數多余2個(大于1的數質數的補集)。

1
2
3
4
5
6
7
8
9
10
11
12
function isPrimeNumber1(n){
if(n < 2) return false;
if(n === 2) return true; // 最小的質數
for(let i = 2; i < n; i++){
if(n % i === 0){
return false;
}
}
return true;
}

測試:isPrimeNumber1(2) // true

最小公約數

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function greatestCommonDivisor1(a, b){
if(a < 0 || b < 0) throw new Error('參數只能為正整數');
if(a < 2 || b < 2) return 1;
let min = a,
max = b,
arymin = [];
if(a > b) {
min = b;
max = a;
}
for(let i = 1; i <= min; i++){
if(min % i === 0){
arymin.push(i);
console.log(1)
}
}
arymin.reverse();
for(let j = 0, len = arymin.length; j < len; j++){
if(max % arymin[j] === 0){
return arymin[j];
}
}
}

測試:greatestCommonDivisor1(5, 10) // 5

金額轉大寫

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function money2Chinese(num) {
if(typeof num) throw new Error('參數為數字')
let strOutput = ""
let strUnit = '仟佰拾億仟佰拾萬仟佰拾元角分'
num += "00"
const intPos = num.indexOf('.')
if (intPos >= 0) {
num = num.substring(0, intPos) + num.substr(intPos + 1, 2)
}
strUnit = strUnit.substr(strUnit.length - num.length)
for (let i = 0; i < num.length; i++) {
strOutput += '零壹貳叁肆伍陸柒捌玖'.substr(num.substr(i, 1), 1) + strUnit.substr(i, 1)
}
return strOutput.replace(/零角零分$/, '整').replace(/零[仟佰拾]/g, '零').replace(/零{2,}/g, '零').replace(/零([億|萬])/g, '$1').replace(/零+元/, '元').replace(/億零{0,3}萬/, '億').replace(/^元/, "零元");
}

測試:money2Chinese(1234) // 壹仟貳佰叁拾肆元整

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/247550.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/247550.shtml
英文地址,請注明出處:http://en.pswp.cn/news/247550.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

stylus

stylus格式 指將css中{} &#xff1b;去掉即可

隨筆記錄(2019.7.10)

1、ISO/OSI 網絡七層參考模型 物理層 數據鏈路層 網絡層 傳輸層 會話層 表示層 應用層 2、 TCP/IP 網絡四層模型和五層模型 四層模型&#xff1a; 網絡接口層 網絡層 傳輸層 應用層 五層模型&#xff1a; 物理層 數據鏈路層 網絡層 傳輸層 應用層 3、 協議簇 &#xff08;1&a…

轉發:Ajax動態畫EChart圖表

本人由于項目需要&#xff0c;在狀態變化的時候需要動態繪制對應數據的EChart圖表&#xff0c;并且不刷新整個網頁。 所以就用Ajax動態畫EChart圖表&#xff0c;下面是開發過程中遇到的一些坑的總結。 流程&#xff1a;頁面首次加載時展示一幅原始的圖形&#xff0c;若后臺數據…

如果硬盤不顯示可以這么處理

http://www.zhuangjiba.com/soft/9574.html轉載于:https://www.cnblogs.com/braveheart007/p/11167311.html

Highcharts的餅圖大小的控制

在Highcharts中&#xff0c;餅圖的大小是Highcharts自動計算并進行繪制。餅圖的大小受數據標簽大小、數據標簽到切片的距離影響。當數據標簽內容較多&#xff0c;并且距離切片較遠時&#xff0c;餅圖就會被壓縮的很小。解決這個問題&#xff0c;有以下幾種方法&#xff1a;&…

轉:谷歌離線地圖基礎

一.需要文件 gapi3文件夾&#xff1a;存放接口等tilemap文件夾&#xff1a;存放圖片gapi.js文件maptool.js文件 二.html配置 <script type"text/javascript" src"gapi.js"></script> <script type"text/javascript" src"map…

HTTP Header 詳解

搜集資料 HTTP&#xff08;HyperTextTransferProtocol&#xff09;即超文本傳輸協議&#xff0c;目前網頁傳輸的的通用協議。HTTP協議采用了請求/響應模型&#xff0c;瀏覽器或其他客戶端發出請求&#xff0c;服務器給與響應。就整個網絡資源傳輸而言&#xff0c;包括message-h…

Windows CE 6.0中斷處理過程(轉載)

這里我們主要討論的是CE的中斷建立和中斷相應的大概流程以及所涉及的代碼位置。這里所講述的&#xff0c;是針對ARM平臺的。在CE的中斷處理里面&#xff0c;有一部分工作是CE Kernel完成的&#xff0c;有一部分工作是要由OEM完成的。 Kernel代碼工作 ExVector.s&#xff1a;中斷…

document.createDocumentFragment 以及創建節點速度比較

document.createDocumentFragment document.createDocumentFragment()方法創建一個新空白的DocumentFragment對象。 DocumentFragments是DOM節點。它們不是主DOM樹的一部分。通常的用例是創建文檔片段&#xff0c;將元素附加到文檔片段&#xff0c;然后將文檔片段附加到DOM樹。…

Javascript重溫OOP之原型與原型鏈

prototype原型對象 每個函數都有一個默認的prototype屬性&#xff0c;其實際上還是一個對象&#xff0c;如果被用在繼承中&#xff0c;姑且叫做原型對象。 在構造函數中的prototype中定義的屬性和方法&#xff0c;會被創建的對象所繼承下來。舉個栗子&#xff1a; function F()…

webpack超詳細配置

在這里就不詳細介紹webpack來源以及作用了, 本篇博文面向新手主要說明如何配置webpack, 以及webpack的使用方法, 直到創建出一個合理的屬于自己webpack項目; 流程 webpack安裝 Step 1: 首先安裝Node.js, 可以去Node.js官網下載.Step2: 在Git或者cmd中輸入下面這段代碼, 通過全局…

小白十分鐘-推薦導航欄

大腿繞道&#xff0c;給小白學習用&#xff0c;上代碼 <div class"list"><div class"infor"><ul class"left"><li><a href"">限時特價</a></li><li><a href"">熱門推…

Underscore.js常用方法介紹

Underscore.js是一個很精干的庫&#xff0c;壓縮后只有4KB。它提供了幾十種函數式編程的方法&#xff0c;彌補了標準庫的不足&#xff0c;大大方便了JavaScript的編程。MVC框架Backbone.js就將這個庫作為自己的工具庫。除了可以在瀏覽器環境使用&#xff0c;Underscore.js還可以…

掌握ES6/ES2015核心內容

ECMAScript 6&#xff08;以下簡稱ES6&#xff09;是JavaScript語言的下一代標準。因為當前版本的ES6是在2015年發布的&#xff0c;所以又稱ECMAScript 2015。 也就是說&#xff0c;ES6就是ES2015。 雖然目前并不是所有瀏覽器都能兼容ES6全部特性&#xff0c;但越來越多的程序員…

express-generator——Express應用生成器賊快!

通過應用生成器工具 express 可以快速創建一個應用的骨架。 通過如下命令安裝&#xff1a; $ npm install express-generator -g-h 選項可以列出所有可用的命令行選項&#xff1a; $ express -hUsage: express [options] [dir]Options:-h, --help output usage inform…

轉:canvas--放大鏡效果

<!DOCTYPE html><html><head><meta charset"UTF-8"><title>鼠標事件</title></head><body><canvas id"canvas"></canvas><canvas id"offCanvas" style" display: none;&qu…

MON

早上5點,咪咪牛就醒了,開始跳到我邊上,用白毛毛把我弄醒,在我身上走來走去,把她按住撫摸也不能讓她停止.....只能拎起來扔到邊上了 ;)看起來還的確是很調皮的貓咪呢昨天晚上就開始不太怕我了,走到我的椅子邊上喵喵叫,直到把她放在身上,才慢慢睡覺,滿可愛的早上出門叫車,一車正停…

CSS做個Switch開關

Switch開關&#xff1a;根據需求可知&#xff0c;Switch開關只有兩種選擇&#xff0c;true或false。所以我們想到HTML的checkbox控件&#xff0c;用它來做。  <input id"switch" type"checkbox" class"switch" />但是在瀏覽器中&#xf…

vue小記錄1

1.入口index.html文件 做reset.css初始化&#xff0c;視口viewport設置 2.規范化eslint配置&#xff08;常用&#xff09; &#xff08;1&#xff09;rules -->"semi"分號 "semi":[error,alway], &#xff08;2&#xff09;indent 空格 "inde…

解決虛擬機能ping通宿主機,而宿主機不能ping通虛擬機

解決虛擬機能ping通宿主機&#xff0c;而宿主機不能ping通虛擬機 首先&#xff0c;查看宿主機的網卡狀態 如果沒有&#xff0c;打開虛擬機&#xff0c;選擇編輯 打開虛擬網絡編輯器&#xff0c;并選擇更改設置 勾選將設備適配器連接此網絡 完成&#xff0c;這樣宿主機便可以pin…