# 阿里前端算法題
```
/**
* 编码题一:判断括号匹配
* 说明:给定一个只包含 '() {} []' 6种字符的字符串,
* 实现一个方法来检测该字符串是否合法,其规则为'()'、'{}'、'[]'必须互相匹配,可嵌套。
* 示例:
* isValid('('); // false
* isValid('()'); // true
* isValid('()[]{}'); // true
* isValid('{()[]}'); // true
* isValid('(]'); // false
* isValid('([)]'); // false
* isValid('({}[]([]))'); // true
*/
//我的答案:
// 1.用stack特性
function isValid(input){
var stack = {};
var size = 0;
var left = ['(', '[', '{'];
var right = [')', ']', '}'];
for(var i = 0; i < input.length; i++){
if( left.indexOf(input[i]) !== -1 ){
stack[size] = input[i];
size++;
} else if( right.indexOf(input[i]) !== -1 ){
if(size === 0) {
return false;
}
var index = right.indexOf(input[i]);
if(stack[size-1] === left[index] ){
size = size-1;
} else {
return false;
}
}
}
return size === 0;
}
/**
* 编码题二:数组按嵌套层次输出
* 说明:给定一个嵌套数组,输出每层的内容
* 示例:
* parseArrayLevels([1, [3, ['x', 'y'], 2], [[5], 'a']]);
* 输出:[[1], [3, 2, 'a'], ['x', 'y', 5]]
*/
//我的答案:
// 使用split() 方法
// (recursion 的solution寫不出來)
function parseArrayLevels(arr) {
/** 代码实现 */
// 方法1.
let stringList = arr.toString().split("'").filter(ele=>{
return ele
})
return stringList
};
/**
* 编码题三:字符串压缩
* 说明:将字符串中连续出席的重复字母进行压缩,并输出压缩后的字符串。
* 压缩规则:
* 1、仅压缩连续重复出现的字符。比如字符串“abcbc”由于无连续重复字符,压缩后的字符串还是”abcbc”
* 2、压缩字段的格式为”字符重复的次数+字符”
* 示例:
* stringZip('cccddecc'); // '3c2de2c'
* stringZip('adef'); // 'adef'
* stringZip('aaaaa'); // '5a'
*/
//我的答案: 用object['a'] 鍵值 這種方法 來記數 (答案有錯)
function stringZip(str) {
/** 代码实现 */
let obj = {}
for(let i=0;i<str.length;i++){ //如果還沒碰過 初始設1
obj[str[i]] = obj[str[i]] +1 || 1
}
let result = ''
for (const [key, value] of Object.entries(obj)) { //拼接字符串
if(parseInt(value)===1){
result += (key)
}else{
result += (key) + (value)
}
}
return result
};
/**
* 编码题四:实现一个检验对象是否循环指向的方法
* 说明:当一个对象存在对自身引用时,称之为循环指向
* 如`var o = { a: {} }; o.a = o;`
* o -> a -> o,就形成循环指向
* 示例:
* isCyclic(window); // true
* isCyclic({}); // false
* var o = {}; o.o = o;
* isCyclic(o); // true
*
* var obj = { foo: { bar: { baz: { qux: {} } } } };
* obj.foo.bar.baz.qux = obj.foo;
* isCyclic(obj); // true
*/
//我的答案:
// 使用JSON.stringify 的特性 , JSON.stringify 會拋異常 如果有 循环指向
// (recursion 的solution寫不出來)
function isCyclic (obj) {
/* 代码实现 */
try {
JSON.stringify(obj);
return false;
} catch (e) {
return true;
}
}
/**
* 编码题五:实现一个评星方法
* 说明:
* 1. 可根据传入的评分和总数,返回评星结果(用 ★ 和 ☆ 描述)
* 2. 评分必选项,四舍五入,总数可选,大于0的整数,默认为5
* 3. 对于评分为空或小于0、评分大于总数、总数小于0或总数非整数的情况,返回'errror'
*
* 示例:
* getRate(4); // ★★★★☆
* getRate(4, 8); // ★★★★☆☆☆☆
* getRate(3.4); // ★★★☆☆
* getRate(5, 2); // 'error'
* getRate(-2); // 'error'
* getRate(3, 5.5); // 'error'
*/
//我的答案:
//用Math.round()四捨五入 並用數組創建result
function getRate(stars,max=5) {
/* 代码实现 */
stars = parseInt(stars)
stars = Math.round(stars)
max = parseInt(max)
if(!stars || stars<0 || stars>max){
return 'error'
}
let result =[]
for(let i=0;i<max;i++){
result.push("☆")
}
for(let i=0;i<stars;i++){
result[i] = '★'
}
return result.join("")
}
```
# 阿里前端題
# thread vs process
### 我的回答:
threads run in a shared memory space, and processes run in separate memory spaces.
linux 下 命令有 ps ,top ,
# 講講項目經驗碰到的難點
### 我的回答:
在之前的項目裡 數據加密沒有做過 文件上傳也沒有做過.....
# javascript代码执行的时候会将不同的变量存于内存中的不同位置:堆(heap)和栈(stack) 你來講講
### 我的回答:
我猜 heap 是 new 出來的dynamic allowcate space
跟c++ 一樣 從動態的
stack 存些 interger 跟string
# 项目中如何处理安全问题
後端的話
加密算法 有 Encryption 跟 Hashing,
密碼用 Hashing 因為難破解
然後前端多對數據檢查 不要相信user input
# 前端性能提升大致分几类
1. 代碼判斷 少發請求 能合併就合併
2. 少render 避免dom re-render
3. 少用event listener 用了要刪
# 拼室友前端考題
1. 什么是深拷贝,和浅拷贝有什么区别,动手实现一个深拷贝
### 我的回答:
像c++中的 copy contrucotor 每個 兒子孫子都copy到
```
function cloneDeep(obj) {
if(obj === null) return null;
if (typeof obj !== 'object') return obj;
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj);
// 获取obj的构造函数并实例化一个新的
const cloneObj = new obj.constructor();
Object.keys(obj).forEach(key => {
// 递归拷贝属性
cloneObj[key] = cloneDeep(obj[key]);
});
return cloneObj;
}
```
2. setTimeout 与 setInterval 区别
### 我的回答:
setTimeout 只跑一次
setInterval 能一直跑
然後都是異步任務
3. 说一下 base64 的编码方式
### 我的回答:
用在傳輸 不是加密 原理不知道
unix 下 可以直接這樣轉換
```
echo '我將被轉' | base64
```
### javascript 的 Promise.then 是什麼
### 我的回答:
異步編程的方法 解決call back hill ,代碼變得的好讀
```
var databaseQuery = new Promise((resolve, reject) => {
resolve('Success!');
});
databaseQuery.then(value => {
console.log("查找成功");
}.err (msg => {
console.log("查找失敗");
})
```
### 介绍下 javascript 的this
### 我的回答:
this 指向當前scope 的對象
全局就指向 window
一般都由內而外
### Linux 754 是什麼
有個command 叫chmod 管 read,write permission的 777 是大家都能看
, 754 好像是 group 的不能看
### 講一下JavaScript中的Event Loop
因為javascript是 single thread 所以 要靠 Event Loop 來處理異步任務
但細節我沒有搞懂
### http 100 是什麼
不知道 但肯定不常用 一般都是200 是好的 300 redirect , 400 canot find , 500 internal error
# 騰訊
```
// - 3. 用JS写一个函数,进行字符串大数相加,输入'56789'+'56789',输出'113578'
function add (a, b) {
let max = a.length > b.length ? a.length :b.length ;
a = a.padStart(max, '0');
b = b.padStart(max, '0');
let result = [];
for (let i = max - 1; i >= 0; i--) {
let sum = Number(a[i]) + Number(b[i]) + (result[0] ? result[0] : 0);
let digit = sum % 10;
let carry = Math.floor(sum / 10);
result[0] = digit;
result.unshift(carry);
}
return result.toString();
}
```
# 騰訊
```
function add(a ,b){
//取两个数字的最大长度
let maxLength = Math.max(a.length, b.length);
//用0去补齐长度
a = a.padStart(maxLength , 0);//"0009007199254740991"
b = b.padStart(maxLength , 0);//"1234567899999999999"
//定义加法过程中需要用到的变量
let t = 0;
let f = 0; //"进位"
let sum = "";
for(let i=maxLength-1 ; i>=0 ; i--){
t = parseInt(a[i]) + parseInt(b[i]) + f;
f = Math.floor(t/10);
sum = t%10 + sum;
}
if(f == 1){
sum = "1" + sum;
}
return sum;
}
```