【路飞】1122. 数组的相对排序、164. 最大间距

188 阅读1分钟

1122. 数组的相对排序

给你两个数组,arr1 和 arr2,arr2 中的元素各不相同,arr2 中的每个元素都出现在 arr1 中。

对 arr1 中的元素进行排序,使 arr1 中项的相对顺序和 arr2 中的相对顺序相同。未在 arr2 中出现过的元素需要按照升序放在 arr1 的末尾。

示例 1:

输入:arr1 = [2,3,1,3,2,4,6,7,9,2,19], arr2 = [2,1,4,3,9,6]
输出:[2,2,2,1,4,3,3,9,6,7,19]

示例  2:

输入: arr1 = [28,6,22,8,44,17], arr2 = [22,28,8,6]
输出: [22,28,8,6,17,44]

解题思路:这题用到的是计数排序,就是先将每种数据都记录下来,然后排序,代码如下:

var relativeSortArray = function(arr1, arr2) {
    //边界条件判断
    if(arr1.length <= 1) return [];
    //记录每个数字出现的次数
    let a1 = {};
    //保存按照arr2排序的数字
    let ans = [];
    //记录每个数字出现的次数
    for(let i = 0; i < arr1.length; i ++){
        if(!a1[arr1[i]]) a1[arr1[i]] = 0;
        a1[arr1[i]] ++;
    }
    //按照arr2排序,如果json key是数字或者字符串会按照key自动排序,字母不会
    for(let i = 0; i < arr2.length; i ++){
        while(a1[arr2[i]]){
            ans.push(arr2[i]);
            a1[arr2[i]] --;
        }
    }
    //给剩下的不在arr2里的数字排序,因为
    for(let i in a1){
        if(a1[i] == 0) continue;
        while(a1[i]){
            ans.push(i);
            a1[i] --;
        }
    }
    return ans;
};

164. 最大间距

给定一个无序的数组 nums,返回 数组在排序之后,相邻元素之间最大的差值 。如果数组元素个数小于 2,则返回 0 。

您必须编写一个在「线性时间」内运行并使用「线性额外空间」的算法。 示例 1:

输入: nums = [3,6,9,1]
输出: 3
解释: 排序后的数组是 [1,3,6,9], 其中相邻元素 (3,6) 和 (6,9) 之间都存在最大差值 3

示例 2:

输入: nums = [10]
输出: 0
解释: 数组元素个数小于 2,因此返回 0。

解题思路:这题用到的是基数排序,分别给地位16排序和高位排序,基数排序就是想对个位数计数然后现将个位数排序,然后依次给十位百位排序,代码如下:

var maximumGap = function(nums) {
    if(nums.length <= 1) return 0;
    //统计每个低16数的个数
    let ans = {};
    //保存排序后的数组
    let data = [];
    //第16位排序
    for(let i = 0; i < nums.length; i ++){
        if(!ans[low16(nums[i])]) ans[low16(nums[i])] = 0;
        ans[low16(nums[i])] ++;   
    }
    let sum = -1,pre = 0;
    //给计数的数求前缀和,然后知道每个对应的位置范围
    for(let i in ans){
        if(sum == -1) ans[i] = ans[i];
        else ans[i] = ans[pre] + ans[i];
        sum = ans[i];
        pre = i;
    }
    //从末尾开始 遍历数组,将计数的数字归位
    for(let i = nums.length - 1; i >= 0; i --){
        data[-- ans[nums[i] & 0xffff] ] = nums[i];
    }
    // 高16位排序,与低位数排序是一样的
    ans = {};//重置ans重新记录高位16排序
    for(let i = 0; i < data.length; i ++){
        if(!ans[high16(data[i])]) ans[high16(data[i])] = 0;
        ans[high16(data[i])] ++;
    }
    sum = -1,pre = 0;
    for(let i in ans){
        if(sum == -1) ans[i] = ans[i];
        else ans[i] = ans[pre] + ans[i];
        sum = ans[i];
        pre = i;
    }
    let data2 = [];
     for(let i = data.length - 1; i >= 0; i --){
          data2[-- ans[high16(data[i])]] = data[i];
    }
    let data3 = [];
    for(let i = 1; i < data2.length; i ++){
        data3.push(data2[i] - data2[i -1]);
    }
    data3.sort(function(a,b){
        return b-a;
    })
    return data3[0];
};
let low16 = function(val){
    return val & 0xffff;
}
// 负数处理
let high16 = function(val){
    return __hight16(val) > 32767 ? (__hight16(val) - 32767) : (__hight16(val) + 32767);
}
let __hight16 = function(val){
    return (val & 0xffff0000) >> 16;
}