# 算法题

# 一、入门

# 1. 遍历数组

function ergodic() {
    var arr = ['red', 'green', 'blue'];
        for (var i = 0; i < 3; i++) {
            console.log(arr[i]);
        }
}
ergodic()

# 2. 旋转数组k个项

const fn = (arr,n) => {
	for (let i = 0; i < n; i++) {
    	let value = arr.pop()
        arr.unshift(value)   
    }
        return arr;
}
console.log(fn([1, 2, 3, 4, 5, 6, 7],2))  // [5, 6, 7, 1, 2, 3, 4]

# 3. 翻转数组

function reverse(arr) {
    var newArr = []; 
    for (var i = arr.length - 1; i >= 0; i--) {
        newArr[newArr.length] = arr[i];
    }
    return newArr;
}
var arr1 = reverse([1, 3, 4, 6, 9]);
console.log(arr1);
var arr2 = reverse(['red','pink','blue']);
console.log(arr2);

# 4. 遍历对象

var o = {a:4, b:1, e:2}
for (var k in o) {
    // k 得到的是 属性名    
    console.log(k);
    // o[k] 得到的是属性值  
    console.log(o[k]);
}

# 5. 九九乘法表

function multiplication() {
    var str = '';
        for (var i = 1; i <= 9; i++) {
            for (var j = 1; j <= i; j++) {
                // 1 x 2 = 2;
                str += j + 'x' + i + '=' + i * j + '\t';
            }
            str = str + '\n';
        }
        console.log(str);
}
multiplication()

# 6. 正三角

function regular() {
    var str = '';
        for (var i = 1; i <= 10; i++) {   
            for (var j = 1; j <= i; j++) {  
                str = str + '◆';
            }
            str = str + '\n';
        }
        console.log(str);
}
regular()

# 7. 倒三角

function inverted() {
    var str = '';
        for (var i = 1; i <= 10; i++) {   
        // 外层循环控制行数
            for (var j = i; j <= 10; j++) {  
            // 内层循环打印的个数不一样 j = i;
                str = str + '★';
            }
            str = str + '\n';
        }
        console.log(str);
}
inverted()

# 8. 递归函数

(自己调用自己的函数)

function f(n){
    if(n === 1) return 1;
    return f(n - 1) + n
}
let a = f(4)
console.log(a)  // 10

// f(1) = 1
// f(2) = f(1) + 2 = 3
// f(3) = f(2) + 3 = [f(1) + 2] + 3 = [1 + 2] + 3 = 6
// f(4) = f(3) + 4 = [f(2) + 3] + 4 = [(f(1) + 2) + 3] + 4 = 10

# 9. 统计素数的总数

function count(num) {
  if ( num < 0) return 'num 必须大于 0';
  var c = 0;
  for (var i = 2; i <= num; i++) {
    // 统计 2~num-1 中的素数的总数
    if (su(i)) c++;
  }
  return c;
  function su(num) {
    if ( num < 0) return false;
    for (var i = 2; i <= num - 1; i++) {
      if(num % i === 0) {
        return false;
      }
    }
    return true;
  }
}
console.log(count(5));

# 10. 判断回文串

function huiwen(str) {
  //(1)反转
  //(2)比较
  return str.split('').reverse().join('') === str;   
  // split: 字符转换为数组,跟 join 相反
  // reverse:反转数组的方法
  // join:数组转换为字符串
}
console.log(huiwen("aba"));

# 二、简单

# 1. 冒泡排序

算法思路:外部循环控制所有的趟数,内部循环代表每一轮的冒泡处理,先进行元素比较,再进行元素交换。
相邻的元素两两比较,根据大小来交换元素的位置

function sort(arr) {
    for (let i = 0; i < arr.length - 1; i++) {
        for (let j = 0; j < arr.length - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                let temp = arr [j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
                // 上面三行代码也可以用 ES6 的一行代码表示:
                // [nums[i], nums[j]] = [nums[j], nums[i]];
            }
        }
    }
    return arr;
}
console.log(sort([1,4,2,9]));

# 2. 排他思想

算法思路:给一组元素中的某一个元素设置样式(先干掉其他人,再设置自己 )

<button>按钮1</button>
<button>按钮2</button>
var btns = document.getElementsByTagName('button');
// button 得到的是伪数组,里面的每一个元素 btns[i]
for (var i = 0; i < btns.length; i++) {
    btns[i].onclick = function () {
        // (1) 去掉所有按钮背景颜色
        for (var i = 0; i < btns.length; i++) {
            btns[i].style.backgroundColor = '';
        }
        // (2) 给当前点击的元素添加背景颜色
        this.style.backgroundColor = 'pink';
    }
}

# 3. 数组去重

核心算法:遍历数组,拿着旧数组元素去查询新数组,如果该元素不在新数组里就添加,否则不添加
利用 .indexOf(数组元素) 如果返回-1 说明新数组没有该元素.

function unique(arr) {
    var newArr = [];
    for (var i = 0; i < arr.length; i++) {
        if (newArr.indexOf(arr[i]) === -1) {
            newArr.push(arr[i]);
        }
    }
    return newArr;
}
var demo = unique(['c', 'd', 'a', 'z', 'c', 'a', 'b']);
console.log(demo);

# 4. 斐波那契数列

数学递归的方法来定义: [1, 1, 2, 3, 5, 8 .... ]

F(0) = 0;
F(1) = 1;
F(n) = F(n - 1) + F(n - 2);
function fib(n) {
    if(n < 0) throw new Error('输入的数字不能小于0');
    if (n < 2) {
        return n;
    }
    return fib(n - 1) + fib(n - 2);
}

# 三、中等

# 1. 判断是否顺子

判断5张牌是否是顺子(大小王可以变成任意牌)

首先将数组排序 再统计0的个数和相邻数字之间的空缺总数 如果空缺总数小于或等于0的个数,那么这个数组就是连续的,反之不连续

bool IsContinuous(int* number, int length)
{
    if(numbers == NULL || length < 1)
    {
        return false;
    }

    qsort(numbers,length,sizeof(int), compare);
    
    int numberOfZero = 0;
    int numberOfGap = 0;
    
    // 统计0的个数
    for(int i = 0; i < length && number[i] == 0; ++i)
    {
        ++numberOfZero;
    }
    
    // 统计数组中间隔数目
    int small = numberOfZero;
    int big = small + 1; 

   while(big < length)
   {
       if(numbers[small] == numbers[big])       
           return false;
       numberOfGap += number[big] - numbers[small] - 1;
       small = big;
       ++big;
   }
    return (numberOfGap > numberOfZero) ? false : true;  
}

int compare(void *arg1,void *arg2)
{
    return *(int *)arg1 - *(int *)arg2;
}