[路飞_js算法:第 k 个数 柠檬水找零 煎饼排序 任务调度器]

160 阅读2分钟

第 k 个数

问题描述: 有些数的素因子只有 3,5,7,请设计一个算法找出第 k 个数。注意,不是必须有这些素因子,而是必须不包含其他的素因子。例如,前几个数按顺序应该是 1,3,5,7,9,15,21。(by leetcode 17.09

示例 1:

输入: k = 5
输出: 9

思路: 建立三个指针,往数组中填数。找到最小的,指定指针往后移动。

var getKthMagicNumber = function(k) {
    let k1=0,k2=0;k3=0,data=[1];
    while(data.length<k){
        let temp=Math.min(data[k1]*3,data[k2]*5,data[k3]*7);
        if(temp==data[k1]*3)k1++;
        if(temp==data[k2]*5)k2++;
        if(temp==data[k3]*7)k3++;
        data.push(temp)
    }
    return data[k-1]

};

柠檬水找零

问题描述: 在柠檬水摊上,每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。

每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。

注意,一开始你手头没有任何零钱。

给你一个整数数组 bills ,其中 bills[i] 是第 i 位顾客付的账。如果你能给每位顾客正确找零,返回 true ,否则返回 false 。(by leetcode 860

示例 1:

输入:bills = [5,5,5,10,20]
输出:true
解释:
前 3 位顾客那里,我们按顺序收取 35 美元的钞票。
第 4 位顾客那里,我们收取一张 10 美元的钞票,并返还 5 美元。
第 5 位顾客那里,我们找还一张 10 美元的钞票和一张 5 美元的钞票。
由于所有客户都得到了正确的找零,所以我们输出 true

思路:

/**
 \* @param {number[]} bills
 \* @return {boolean}
 */
var lemonadeChange = function(bills) {
     let arr={
         '5':0,
         '10':0
     }
     for(let i=0;i<bills.length;i++){
         if(bills[i]==5){
             arr['5']++;
         }
         if(bills[i]==10){
             if(!arr['5'])return false;
             arr['5']--;
             arr['10']++;
         }
         if(bills[i]==20){
            if(!arr['5'])return false;
            if(arr['10']){
                arr['5']--;
                arr['10']--;
            }
            else{
                if( arr['5']<3)return false;
                arr['5']-=3;
            }
         }
     }
     return true
};

煎饼排序

问题描述: 给你一个整数数组 arr ,请使用 煎饼翻转 完成对数组的排序。(by leetcode 969)

​ 一次煎饼翻转的执行过程如下:

  • 选择一个整数 k1 <= k <= arr.length
  • 反转子数组 arr[0...k-1]下标从 0 开始

例如,arr = [3,2,1,4] ,选择 k = 3 进行一次煎饼翻转,反转子数组 [3,2,1] ,得到 arr = [**1**,**2**,**3**,4]

以数组形式返回能使 arr 有序的煎饼翻转操作所对应的 k 值序列。任何将数组排序且翻转次数在 10 * arr.length 范围内的有效答案都将被判断为正确。

示例 1:

输入:[3,2,4,1]
输出:[4,2,4,3]
解释:
我们执行 4 次煎饼翻转,k 值分别为 424,和 3。
初始状态 arr = [3, 2, 4, 1]
第一次翻转后(k = 4):arr = [1, 4, 2, 3]
第二次翻转后(k = 2):arr = [4, 1, 2, 3]
第三次翻转后(k = 4):arr = [3, 2, 1, 4]
第四次翻转后(k = 3):arr = [1, 2, 3, 4],此时已完成排序。 

思路:

方案:第一轮,找到最大的,然后翻转它之前的(包括他本身),此时本轮最大的跑到最前面。再整体翻转全部。

第二轮,忽略最后一位,重复第一轮的操作。

第三轮,忽略倒数两位,重复第一轮操作,以此类推,直到只剩一位,不需要操作。

/**
 * @param {number[]} arr
 * @return {number[]}
 */
//翻转
function reverse(arr,index,ind){
    for(let i=0,j=index-1;i<j;i++,j--){
        [arr[i],arr[j]]=[arr[j],arr[i]];
        ind[arr[i]]=i;
        ind[arr[j]]=j;
    }
}
 var pancakeSort = function(arr) {
     let index=[0];
     let ret=[];
     for(let i=0;i<arr.length;i++){
         index[arr[i]]=i;//将值用下标记录(没有值为0的,因此长度加1)
     }
     for(let i=arr.length;i>=1;i--){//针对每一轮处理翻转,只剩一个值不需要翻转
         if(index[i]==i+1)continue;//值在正确的位置上,不需要翻转
         if(i+1!==1){
         ret.push(index[i]+1);//
         reverse(arr,index[i]+1,index);}//翻转i+1位
         if(i!=1){
          ret.push(i);
         reverse(arr,i,index);
         }
     }
     return ret;
};

任务调度器

问题描述: 给你一个用字符数组 tasks 表示的 CPU 需要执行的任务列表。其中每个字母表示一种不同种类的任务。任务可以以任意顺序执行,并且每个任务都可以在 1 个单位时间内执行完。在任何一个单位时间,CPU 可以完成一个任务,或者处于待命状态。

然而,两个 相同种类 的任务之间必须有长度为整数 n 的冷却时间,因此至少有连续 n 个单位时间内 CPU 在执行不同的任务,或者在待命状态。(by leetcode 621

你需要计算完成所有任务所需要的 最短时间

示例 1:

输入:tasks = ["A","A","A","B","B","B"], n = 2
输出:8
解释:A -> B -> (待命) -> A -> B -> (待命) -> A -> B
     在本示例中,两个相同类型任务之间必须间隔长度为 n = 2 的冷却时间,而执行一个任务只需要一个单位时间,所以中间出现了(待命)状态。 

思路:

只有两种情况:1.用任务填充待命区时,待命区还有空位。2.填满为任务总长度。

因此就是取两者最长的值。

/**
 * @param {character[]} tasks
 * @param {number} n
 * @return {number}
 */
var leastInterval = function(tasks, n) {
  let arrMap=new Array(26).fill(0);
for(let i=0;i<tasks.length;i++){
    arrMap[tasks[i].charCodeAt(0)-'A'.charCodeAt(0)]++;
}
////console.log(arrMap)
let max=0;
let maxlength=0;
for(let i=0;i<arrMap.length;i++){
    if(arrMap[i]>max){
        maxlength=1;
        max=arrMap[i];
    }else if(arrMap[i]==max){
        maxlength++
    }
}
//console.log(maxlength)
return Math.max((max-1)*(n+1)+maxlength,tasks.length)
};