FCC高级算法题

2017-01-11 ♪砖头文_

1、Validate US Telephone Numbers

如果传入字符串是一个有效的美国电话号码,则返回 true。

下面是一些有效号码的例子(还有下面测试时用到的一些变体写法):
555-555-5555
(555)555-5555
(555) 555-5555
555 555 5555
5555555555
1 555 555 5555

在本节中你会看见如 800-692-7753 or 8oo-six427676;laskdjf这样的字符串。你的任务就是验证前面给出的字符串是否是有效的美国电话号码。区号是必须有的。 如果字符串中给出了国家代码, 你必须验证其是 1。如果号码有效就返回 true ; 否则返回 false。

解答:

function telephoneCheck(str) {
  // Good luck!
  var reg=/^1? ?(d{3}|(d{3}))[ -]?d{3}[ -]?d{4}$/;
  var res=reg.test(str);
  return res;
}


telephoneCheck("2 (757) 622-7382");

2、Symmetric Difference

创建一个函数,接受两个或多个数组,返回所给数组的 对等差分(symmetric difference) (△ or ⊕)数组。

给出两个集合 (如集合 A = {1, 2, 3} 和集合 B = {2, 3, 4}), 而数学术语 "对等差分" 的集合就是指由所有只在两个集合其中之一的元素组成的集合(A △ B = C = {1, 4})。 对于传入的额外集合 (如 D = {2, 3}), 你应该安装前面原则求前两个集合的结果与新集合的对等差分集合 (C △ D = {1, 4} △ {2, 3} = {1, 2, 3, 4})。

解答:

function sym(args) {
  var temp,pos;
  var a=Array.from(arguments);
   a=a.reduce(function(prev, curv, index, array){
    var a = prev.filter(function(item){
      return curv.indexOf(item) < 0;
    });
    var b = curv.filter(function(item){
      return prev.indexOf(item) < 0;
    });
    return a.concat(b);
  });
  return a.filter(function(item,index,array){
    return array.indexOf(item) == index;
  });
}

sym([1, 2, 3], [5, 2, 1, 4]);

3、Exact Change

设计一个收银程序 checkCashRegister() ,其把购买价格(price)作为第一个参数 , 付款金额 (cash)作为第二个参数, 和收银机中零钱 (cid) 作为第三个参数。

cid 是一个二维数组,存着当前可用的找零。

当收银机中的钱不够找零时返回字符串 "Insufficient Funds"。 如果正好则返回字符串 "Closed"。否则, 返回应找回的零钱列表,且由大到小存在二维数组中。

解答:

function checkCashRegister(price, cash, cid) {
  var change;
   var base=100;//金额基数
   change=(cash-price)*base; //找零

    //定义一个函数,用来求零钱和。
    var getTotalMoney=function(arr){  
       var s=arr.reduce(function (preV, currV, currIndex, array){
            return preV+currV[1];
        },0); 
        return base*s;      
    };
    var remain = getTotalMoney(cid);

    if(remain < change){//余额不足,没钱找了
        return "Insufficient Funds";
    }
    
    var baseDollarObj={
      "PENNY":1,
      "NICKEL":5,
      "DIME":10,
      "QUARTER":25,
      "ONE":100,
      "FIVE":500,
      "TEN":1000,
      "TWENTY":2000,
      "ONE HUNDRED":10000
    };
     var changeArr=[];
     var currLast=0;// 当前面值所剩余额
     var currMoney=0;//当前金钱面额
     var currtotal=0;//当前零钱可找总额
     for (var i=cid.length-1;i>=0;i--){
         //当前面值剩余金额
        currLast=cid[i][1]*base;      
        if (currLast<=0) { 
            continue;//当前面值的金额剩余0,跳过
        }
       currMoney=baseDollarObj[cid[i][0]];
        if(change>currMoney){//如果当前金额面值小于应找钱数         
             if(change<currLast){
                currtotal=currMoney*Math.floor(change/currMoney);          
             }else{
               currtotal=currLast;
                          
             }
             change-=currtotal; //取完之后从应找余额中减去(张数x面值) 
             changeArr.push([cid[i][0],currtotal/base]);
     }
     }
  
     if(change>0){
      //找不开的面值
       return "Insufficient Funds";
     }else if(change===0&&((cash-price)*base==remain)){
       //如果零钱数等于应找数额并且可找出来
       return "Closed";  
     }else{
       return changeArr;
     }
}

checkCashRegister(19.50, 20.00, [["PENNY", 0.50], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]]);

4、Inventory Update

依照一个存着新进货物的二维数组,更新存着现有库存(在 arr1 中)的二维数组。 如果货物已存在则更新数量 。如果没有对应货物则把其加入到数组中,更新最新的数量。返回当前的库存数组,且按货物名称的字母顺序排列。

解答:

function updateInventory(arr1, arr2) {
    // All inventory must be accounted for or you're fired!
 arr2=arr2.filter(function(v){
    var res=true;
    for(var i=0;i<arr1.length;i++){
     if(v[1]===arr1[i][1]){
       arr1[i][0]=arr1[i][0]+v[0];
       res= false;
       break;
     }
  }
  return res;
  });
  arr1=arr1.concat(arr2);
  arr1.sort(function(a,b){
    return a[1].charCodeAt(0)-b[1].charCodeAt(0);
  });
    return arr1;
}

// Example inventory lists
var curInv = [
    [21, "Bowling Ball"],
    [2, "Dirty Sock"],
    [1, "Hair Pin"],
    [5, "Microphone"]
];

var newInv = [
    [2, "Hair Pin"],
    [3, "Half-Eaten Apple"],
    [67, "Bowling Ball"],
    [7, "Toothpaste"]
];

updateInventory(curInv, newInv);

5、No repeats please

把一个字符串中的字符重新排列生成新的字符串,返回新生成的字符串里没有连续重复字符的字符串个数.连续重复只以单个字符为准。

例如, aab 应该返回 2 因为它总共有6中排列 (aab, aab, aba, aba, baa, baa), 但是只有两个 (aba and aba)没有连续重复的字符 (在本例中是 a)。

思路:
全排列recoper函数:对于每一个输入的str,我们把它分为两部分,第一部分为字符串的第一个字母,定义为left,第二部分为剩余的字符串,定义为rest。返回str的全排列数组。
递归思路:递归recoper。

解答:

function permAlone(str) {
    var perarr=[];
    //创建正则,如果字符串全重复,则直接return 0
    var reg = /(.)1+/g;
    if (str.match(reg) !== null && str.match(reg)[0] === str) {
      return 0;
    }

    function recoper(str) {
      var arr = [];//存放str的全排列
      if (str.length > 1) {
        var left = str[0];
        var rest = str.slice(1, str.length);
        //获取rest字符串的全排列
        var perRes = recoper(rest);
        var pl = perRes.length,
          pil, s;
        for (var i = 0; i < pl; i++) {
          s = perRes[i];
          pil = perRes[i].length;
          for (var j = 0; j <=pil; j++) {
            var tmp = s.substring(0, j) + left + s.substring(j, pl);
            arr.push(tmp);
          }
        }
      } else if (str.length == 1) {
        arr = [str];
      }
      return arr;
    }
    perarr=recoper(str);
    //返回相邻不重复的数量
    return perarr.filter(function(val) {
      return !val.match(reg);
    }).length;
  }
  permAlone('aab');

6、Friendly Date Ranges

把常见的日期格式如:YYYY-MM-DD 转换成一种更易读的格式。
易读格式应该是用月份名称代替月份数字,用序数词代替数字来表示天 (1st 代替 1)。

记住不要显示那些可以被推测出来的信息: 如果一个日期区间里结束日期与开始日期相差小于一年,则结束日期就不用写年份了。月份开始和结束日期如果在同一个月,则结束日期月份就不用写了。另外, 如果开始日期年份是当前年份,且结束日期与开始日期小于一年,则开始日期的年份也不用写。

解答:

 function makeFriendlyDates(arr) {
    var dateArr = ["", "1st", "2nd", "3rd", "4th", "5th", "6th", "7th", "8th", "9th", "10th",
        "11th", "12th", "13th", "14th", "15th", "16th", "17th", "18th", "19th", "20th",
        "21st", "22nd", "23rd", "24th", "25th", "26th", "27th", "28th", "29th", "30th",
        "31st"
      ],
      monthArr = ["", "January", "February", "March", "April", "May", "June",
        "July", "August", "September", "October", "November", "December"
      ],
      resarr = [];
   //判断是否相差小于一年,true为相差小于一年。
    var caldate = function(startTime, endTime) {
      startTime = startTime.replace(/-/g, "/");
      endTime = endTime.replace(/-/g, "/");
      var newa = new Date(startTime);
      newa.setFullYear(newa.getFullYear() + 1);
      newa = newa.getTime();
      var newb = new Date(endTime).getTime();
      if (newa <= newb) {
        return true;
      } else {
        return false;
      }
    };
    var a = arr[0].replace(/-0?/g, " ").split(" "),
      b = arr[1].replace(/-0?/g, " ").split(" "),
      nowYear = new Date().getFullYear();
    var str1 = monthArr[a[1]] + " " + dateArr[a[2]],
      str2 = dateArr[b[2]];

    var morethanoneyear = caldate(arr[0], arr[1]);

    if (!morethanoneyear) {
      if (a[0] != nowYear){
        //开始日期年份不是当前年份
         str1 = str1 + ", " + a[0];
      }
     
      if ((a[1] === b[1])&&(a[2] === b[2])) {
        //同年同月同日
          str2 = "";
        } else if(!((a[1] === b[1])&&(parseInt(a[2]) < parseInt(b[2])))){
          str2 = monthArr[b[1]] + " " + str2;
        }

    } else {
      //相差超过一年
      str1 = str1 + ", " + a[0];
      str2 = monthArr[b[1]] + " " + str2 + ", " + b[0];
    }

    if (str2 !== "") {
      resarr.push(str1, str2);
    } else {
      resarr.push(str1);
    }
    return resarr;
  }
makeFriendlyDates(["2022-09-05", "2023-09-04"]);

7、Make a Person

用下面给定的方法构造一个对象。方法有 getFirstName(), getLastName(),getFullName(), setFirstName(first), setLastName(last), and setFullName(firstAndLast)。所有有参数的方法只接受一个字符串参数。所有的方法只与实体对象交互。

解答:

var Person = function(firstAndLast) {
    var firstAndLastarr=firstAndLast.split(" "),  firstName=firstAndLastarr[0],
    lastName=firstAndLastarr[1];
    this.getFirstName=function(){
      return firstName;
    };
    this.getLastName=function(){
      return lastName;
    };
    this.getFullName=function(){
      firstAndLastarr[0]=firstName;
      firstAndLastarr[1]=lastName;
      return firstAndLastarr.join(" ");
    };
    this.setFirstName=function(first){
     firstName=first;
    };
    this.setLastName=function(last){
      lastName=last;
    };
    this.setFullName=function(firstAndLast){
    firstAndLastarr=firstAndLast.split(" ");
    firstName=firstAndLastarr[0];
    lastName=firstAndLastarr[1];
    };
}; 
var bob = new Person('Bob Ross');
bob.getFirstName();

8、Map the Debris

返回一个数组,其内容是把原数组中对应元素的平均海拔转换成其对应的轨道周期。
原数组中会包含格式化的对象内容,像这样 {name: 'name', avgAlt: avgAlt}

解答:

function orbitalPeriod(arr) {
  var GM = 398600.4418;
  var earthRadius = 6367.4447;
   for(var i=0;i<arr.length;i++){
    var R=arr[i].avgAlt+earthRadius;
    var T=R*2*Math.PI*Math.sqrt((R/GM));
    delete arr[i].avgAlt;
    arr[i].orbitalPeriod=Math.round(T);
  }
  return arr;
}

orbitalPeriod([{name : "sputnik", avgAlt : 35873.5553}]);

9、Pairwise

有一个能力数组[7,9,11,13,15],按照最佳组合值为20来计算,只有7+13和9+11两种组合。而7在数组的索引为0,13在数组的索引为3,9在数组的索引为1,11在数组的索引为2。
所以我们说函数:pairwise([7,9,11,13,15],20) 的返回值应该是0+3+1+2的和,即6。

第一种解答:

 function pairwise(arr, arg) {
    var a = arr.reduce(function(prev, currv, index, array) {
      var l = array.length;
      for (var i = index + 1; i < l; i++) {
        if (array[index] + array[i] === arg) {
          arr[index] = "false";
          arr[i] = "false";
          return prev + i + index;
        }
      }
      return prev;
    }, 0);
    return a;
  }
pairwise([1,4,2,3,0,5], 7);

第二种解答:

function pairwise(arr, arg) {
  var l=arr.length,res=0;
  for(var i=0;i<l;i++){
    for(var j=i+1;j<l;j++){
      if(arr[i]+arr[j]===arg){
        res=res+i+j;
        arr[i]="false";
        arr[j]="false";
      }
    }
  }
  
  return res;
}
pairwise([1,4,2,3,0,5], 7);

内容来源:https://segmentfault.com/a/1190000008072646


用户评论
开源开发学习小组列表