一道国外前端面试题引发的Coding...

刚刚看到CSDN微信公众号一篇文章,关于国外程序员面试前端遇到的一道测试题,有点意思,遂写了下代码,并记录一下~

 

题目是这样的:

['Tokyo', 'London', 'Rome', 'Donlon', 'Kyoto', 'Paris']
// YOUR ALGORITHM
[
    ['Tokyo', 'Kyoto'],
    ['London', 'Donlon'],
    ['Rome'],
    ['Paris']
]

也就是说给定一个字符串数组:

['Tokyo', 'London', 'Rome', 'Donlon', 'Kyoto', 'Paris']

经过自己写的算法变换后,要得到下面这个数组:

[
    ['Tokyo', 'Kyoto'],
    ['London', 'Donlon'],
    ['Rome'],
    ['Paris']
]

经过观察,原来题目要求把原数组中“相关”的元素组成新的数组,并作为最终答案数组的一个元素。

“相关”的意思是指:如果一个长度为 N 的字符串 A,依次将最左边的字符挪到最右边,重复 N-1 遍,得到 N 个(包含原字符串)字符串中的任意一个,跟字符串 B 相同(不考虑大小写),则认为 A 跟 B “相关”。

于是,先来一个比较函数:

/**
 * 匹配函数 compareString
 * @param strA 要比较的字符串
 * @param strB 要比较的另一个字符串
 * @return 0: 表示匹配, -1: 表示不匹配
 */
function compareString(strA, strB) {
    if(strA.length !== strB.length)return -1;//长度不相等肯定不会匹配,立即返回
    
    var a = strA.toLowerCase();//先将要比较的字符串转换成小写,下同
    var b = strB.toLowerCase();
    var i = 0;
    
    do{
        if(a === b)return 0;//匹配,返回 0
        b = b.substr(1) + b.substr(0, 1);//将第一个字符转移至尾部
        i++;
    }while(i < b.length);
    
    return -1;//360 度检查还没认出来,那 A、B 两个是无缘了~
}

 

假设原数组是:

var dataArr = ['Tokyo', 'London', 'Rome', 'Donlon', 'Kyoto', 'Paris']; 

结果存入:

var result = [];

那么可以如下处理:

while(dataArr.length > 1) {
    var str = dataArr.shift();//取数组第一个元素,与后续元素逐个对比
    var newArr = [];//本轮匹配结果存储的数组
    newArr.push(str);//先将要对比的 str 存入数组
    var i = 0;
    
    //为什么不用 for 循环呢?
    //因为在循环体内可能“剪切”元素导致数组长度变小,所以不能用固定次数循环
    while(i < dataArr.length) {
        if(compareString(str, dataArr[i]) == 0) {//匹配
            newArr.push(dataArr[i]);//将匹配元素加入新数组
            //从原数组中移除当前元素
            //当前元素移除后,后面的元素依次往前移动一格,因此下一次遍历的下标不变
            dataArr.splice(i, 1);
        }else{
            i++;//本轮循环没有匹配上,下一轮匹配轮到后面一个元素,因此下标要加 1
        }
    }
    
    result.push(newArr);//将本次匹配数组加入 result 数组
}

if(dataArr.length > 0)result.push(dataArr);//落单的跟上

用 node 执行,结果如下图:

 

完整代码如下:

/*
['Tokyo', 'London', 'Rome', 'Donlon', 'Kyoto', 'Paris']
// YOUR ALGORITHM
[
    ['Tokyo', 'Kyoto'],
    ['London', 'Donlon'],
    ['Rome'],
    ['Paris']
]
*/

//======================================

/**
 * Coding by Jaffray Tan
 * 2018.07.03
 */
var dataArr = ['Tokyo', 'London', 'Rome', 'Donlon', 'Kyoto', 'Paris']; 
console.log('\nInit array:\n', dataArr);//先输出原数组
var result = [];

while(dataArr.length > 1) {
    var str = dataArr.shift();//取数组第一个元素,与后续元素逐个对比
    var newArr = [];//本轮匹配结果存储的数组
    newArr.push(str);//先将要对比的 str 存入数组
    var i = 0;
    
    //为什么不用 for 循环呢?
    //因为在循环体内可能“剪切”元素导致数组长度变小,所以不能用固定次数循环
    while(i < dataArr.length) {
        if(compareString(str, dataArr[i]) == 0) {//匹配
            newArr.push(dataArr[i]);//将匹配元素加入新数组
            //从原数组中移除当前元素
            //当前元素移除后,后面的元素依次往前移动一格,因此下一次遍历的下标不变
            dataArr.splice(i, 1);
        }else{
            i++;//本轮循环没有匹配上,下一轮匹配轮到后面一个元素,因此下标要加 1
        }
    }
    
    result.push(newArr);//将本次匹配数组加入 result 数组
}

if(dataArr.length > 0)result.push(dataArr);//落单的跟上

console.log('\n\nResult array:\n', result);//输出结果

//=====================================

/**
 * 匹配函数 compareString
 * @param strA 要比较的字符串
 * @param strB 要比较的另一个字符串
 * @return 0: 表示匹配, -1: 表示不匹配
 */
function compareString(strA, strB) {
    if(strA.length !== strB.length)return -1;//长度不相等肯定不会匹配,立即返回
    
    var a = strA.toLowerCase();//先将要比较的字符串转换成小写,下同
    var b = strB.toLowerCase();
    var i = 0;
    
    do{
        if(a === b)return 0;//匹配,返回 0
        b = b.substr(1) + b.substr(0, 1);//将第一个字符转移至尾部
        i++;
    }while(i < b.length);
    
    return -1;//360 度检查还没认出来,那 A、B 两个是无缘了~
}

 

posted @ 2018-07-03 01:39  Jaffray  阅读(651)  评论(2编辑  收藏  举报