面試的一個題,當時只說了算法思路和大概實現步驟,現在我把完整的做出來,嗯嗯嗯,不曉得我這樣算不算複雜,歡迎大家來建議,一起討論討論
給定一個計算式(包含加減乘除四則運算)字符串,計算結果
算法思想:
1)將操作數和操作符分別按順序存放到數組中
此處我用到的方法是parseInt(str),此函數會返回字符串開頭的整數;然後用字符串截取第一個字符str.substring(0, 1)就是操作符,兩個步驟不能條換順序
2)遍歷操作符數組,先計算優先級較高的*和/,所以用Array.includes("*","/")判斷是否包含*和/,若有,找到一個,記住當前索引以及操作符就返回;
記住當前索引既是爲了找到當前的操作符,也是爲了下一次遍歷不從頭開始,減小開銷
3)計算操作符原本相鄰的兩個操作數,進行相應的計算,存儲單步結果
將計算過的兩個數從數組中刪除,將單步結果插入到該位置;操作符同理保證操作數運算順序不改變,操作符順序不改變;
4)返回計算最終結果
因爲最近在學習vue.js所以這個demo使用vue的相關語法寫的,也主要是爲了實時展現數據,方便。若大家有更好的方法,或對我的這個算法有建議,歡迎指教哦。qq:1358025287
同時大家也可以到我的GitHub下載源碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>計算算式結果</title>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="main">
<label for="request">請輸入算式:</label><input type="text" name="request" id="" v-model="str">
<button @click="reset">重置</button>
<button @click="compute(str)">提交</button>
<label for="result">結果:</label><input type="text" name="result" id="" v-model="result">
<!-- 測驗我的nums,和op是否存儲成功 -->
<!-- <div>操作數依次是:{{nums}}</div>
<div>操作符依次是:{{op}}</div> -->
</div>
<script>
var vm = new Vue({
el: "#main",
data: {
str: '', //實時獲取輸入字符串
result: '', //存放計算結果
nums: [], //存放操作數
op: [] //存放操作符
},
methods: {
compute(str) {
// console.log(str);
//循環操作,將操作數和操作符分開
while (str.length) {
let num = parseInt(str);
this.nums.push(num);
let numstr = String(num);
str = str.substr(numstr.length);
// console.log(str);
if (str.length != 0) {
this.op.push(str.substring(0, 1));
str = str.substr(1);
// console.log(str);
}
}
// console.log(this.nums, this.op);
//找到‘*’或‘/’操作符
let index = 0;
let opr = '';
let result;
// console.log(111);
//當op數組不爲空時調用searchOpr
while (this.op.length > 0) {
// 調用函數,找到對應的操作符以及索引
let m = this.searchOpr(index, this.op);
index = m[0];
opr = m[1];
// 計算結果
if (opr === "*") {
// 計算單步結果
result = this.nums[index] * this.nums[index + 1];
// 將計算了的兩個值從nums中刪除,
this.nums.splice(index, 2);
// 並將單步結果加入對應的位置,保證先後順序不亂
this.nums.splice(index, 0, result);
// 刪除計算了的操作符
this.op.splice(index, 1);
// console.log('*',this.nums,this.op);
} else if (opr === "/") {
result = this.nums[index] / this.nums[index + 1];
this.nums.splice(index, 2);
this.nums.splice(index, 0, result);
this.op.splice(index, 1);
// console.log('/',this.nums,this.op);
} else if (opr === "+") {
result = this.nums[index] + this.nums[index + 1];
this.nums.splice(index, 2);
this.nums.splice(index, 0, result);
this.op.splice(index, 1);
// console.log('+',this.nums,this.op);
} else if (opr === "-") {
result = this.nums[index] - this.nums[index + 1];
this.nums.splice(index, 2);
this.nums.splice(index, 0, result);
this.op.splice(index, 1);
// console.log('-',this.nums,this.op);
}
}
this.result = result;
},
// 選擇操作符,並且找到操作符的索引
// 遍歷操作符數組,先找到“*”和“/”,沒有的話就從數組開頭開始計算
searchOpr(index, op) {
let index1;
let opr = '';
if (op.includes("*", "/")) {
for (let i = index; i < op.length; i++) {
if (op[i] === "*") {
opr = '*';
index1 = i;
break;
} else if (op[i] === "/") {
opr = '/';
index1 = i;
break;
}
}
} else {
index1 = 0;
opr = op[0];
}
return [index1, opr];
},
// 點擊重置,清除我所有的數據,而不需要刷新頁面
reset() {
this.nums = [];
this.op = [];
this.result = "";
this.str = "";
}
}
});
</script>
</body>
</html>