---
# System prepended metadata

title: 阿里前端算法題

---


# 阿里前端算法題
```
/**
 * 编码题一：判断括号匹配
 * 说明：给定一个只包含 '() {} []' 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;
}
```