leetcode.1122. 数组的相对排序(relative-sort-array)

1122. 数组的相对排序(relative-sort-array)

给你两个数组,arr1arr2

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 = [2,3,1,3,2,4,6,7,9,2,19], arr2=[4,3,9,6]
输出:[4,3,3,9,6,1,2,2,2,7,19]

提示:

arr1.length, arr2.length <= 1000
0 <= arr1[i], arr2[i] <= 1000
arr2 中的元素 arr2[i] 各不相同
arr2 中的每个元素 arr2[i] 都出现在 arr1 中

代码与思路

这道题目包含的信息很多,关键是看清楚示例的输出,[2,2,2,1,4,3,3,9,6,7,19]前面有三个连着的2,题目说了arr2的中元素是各不相同的,没有说arr1中的元素的特征,但是可以从输入的arr1输出看出,arr1是有重复元素的。题目中还有一点,未在 arr2 中出现过的元素需要按照升序放在 arr1 的末尾,也就是说在新的数组中(返回的那个数组),arr2的元素排在前面。

计数排序

class Solution {
    public int[] relativeSortArray(int[] arr1, int[] arr2) {
        int[] nums = new int[1001];
        int[] res = new int[arr1.length];
        //遍历arr1,统计每个元素的数量
        for (int i : arr1) {
            nums[i]++;
        }
        //遍历arr2,处理arr2中出现的元素
        int index = 0;
        for (int i : arr2) {
            while (nums[i]>0){
                res[index++] = i;
                nums[i]--;
            }
        }
        //遍历nums,处理剩下arr2中未出现的元素
        for (int i = 0; i < nums.length; i++) {
            while (nums[i]>0){
                res[index++] = i;
                nums[i]--;
            }
        }
        return res;
    }
}

纯c实现

/* 封装uthash开始 */
struct HashTable {
    int k;
    int v;
    UT_hash_handle hh;
};

typedef struct HashTable HashTable;
typedef struct HashTable NodeHashTable;

HashTable *newHashTable( void ) {
    return NULL;
}

int putHashTable( HashTable **hashTable, int key, int val ) {
    NodeHashTable *n = NULL;

    HASH_FIND_INT( *hashTable, &key, n );
    if( n == NULL ) {
        n = (NodeHashTable *) malloc( sizeof(*n) );
        n->k = key;
        HASH_ADD_INT( *hashTable, k, n );
    }
    n->v = val;

    return val;
}

int removeHashTable( HashTable **hashTable, int key ) {
    int v = 0;
    NodeHashTable *n = NULL;

    HASH_FIND_INT( *hashTable, &key, n );
    if( n != NULL ) {
        v = n->v;
        HASH_DEL( *hashTable, n );
        free( n );
    }

    return v;
}

int getHashTable( HashTable *hashTable, int key ) {
    NodeHashTable *n = NULL;

    HASH_FIND_INT( hashTable, &key, n );

    return n->v;
}

NodeHashTable *addressHashTable( HashTable *hashTable, int key ) {
    NodeHashTable *n = NULL;

    HASH_FIND_INT( hashTable, &key, n );

    return n;
}

int existHashTable( HashTable *hashTable, int key ) {
    NodeHashTable *n = NULL;

    HASH_FIND_INT( hashTable, &key, n );

    return n != NULL;
}

int sizeHashTable( HashTable *hashTable ) {
    return HASH_COUNT( hashTable );
}

int emptyHashTable( HashTable *hashTable ) {
    return !(HASH_COUNT( hashTable ));
}

void traverseHashTable( HashTable *hashTable ) {
    NodeHashTable *n = NULL;

    for( n = hashTable; n != NULL; n = n->hh.next ) {
        printf( "k = %d, v = %d\n", n->k, n->v );
    }
}

void cleanHashTable( HashTable *hashTable ) {
    NodeHashTable *current = NULL, *temp = NULL;

    HASH_ITER( hh, hashTable, current, temp ) {
        HASH_DEL( hashTable, current );
        free( current );
    }
}

void delHashTable( HashTable *hashTable ) {
    cleanHashTable( hashTable );
}
/* 封装uthash结束 */



/* 随机快排实现开始 */
#if 0
static void array_2elem_swap( int a[], int i, int j ) {
    int temp = a[i];

    a[i] = a[j];
    a[j] = temp;
}
#else
#define                        \
array_2elem_swap( a, i, j ) ({ \
    int i1 = (i), j1 = (j);    \
    int temp = *((a) + i1);    \
    *((a) + i1) = *((a) + j1); \
    *((a) + j1) = temp;        \
})
#endif

static void array_partition( int a[], int left, int right, int boundary[2] ) {
    int l = left - 1, c = left, r = right;

    // left + rand() % (right - left) 取值区间: [left, right).
    // left + rand() % (right - left + 1) 取值区间: [left, right].
    array_2elem_swap( a, left + rand() % (right - left), right );
    while( c < r ) {
        if( a[c] < a[right] ) {
            array_2elem_swap( a, c++, ++l );
        } else if( a[c] > a[right] ) {
            array_2elem_swap( a, c, --r );
        } else {
            ++c;
        }
    }
    array_2elem_swap( a, r, right );
    boundary[0] = l + 1;
    boundary[1] = r;
}

void array_sort_quick( int a[], int left, int right ) {
    int boundary[2] = {-1,-1};

    srand( (unsigned int)time( NULL ) );
    if( left < 0 || left >= right ) {
        return;
    }
    array_partition( a, left, right, boundary );
    array_sort_quick( a, left, boundary[0] - 1 );
    array_sort_quick( a, boundary[1] + 1, right );
}
/* 随机快排实现结束 */



/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int *relativeSortArray(int *arr1, int arr1Size, int *arr2, int arr2Size, int *returnSize ) {
    int *returnArray = NULL, *help = NULL;
    HashTable *hashTable = NULL;
    int i = 0, helpI = 0;
    int count = 0, j = 0;

    returnSize[0] = 0;
    if( arr1Size < 1 || arr2Size < 1 ) {
        return NULL;
    }
    returnArray = (int *) malloc( sizeof(*returnArray) * arr1Size );
    help = (int *) malloc( sizeof(*help) * arr1Size );

    for( i = 0; i < arr2Size; ++i ) { // 把arr2中的元素都加入到哈希表中, 值初始为0.
        putHashTable( &hashTable, arr2[i], 0 );
    }

    for( i = 0; i < arr1Size; ++i ) {
        if( existHashTable( hashTable, arr1[i] ) ) { // arr1[i] 存在arr2中, 利用哈希表统计个数.
            putHashTable( &hashTable, arr1[i], getHashTable( hashTable, arr1[i] ) + 1 );
        } else {
            help[helpI++] = arr1[i];
        }
    }

    for( i = 0; i < arr2Size; ++i ) { // 还原arr2顺序.
        count = getHashTable( hashTable, arr2[i] );
        for( j = 0; j < count; ++j ) {
            returnArray[returnSize[0]++] = arr2[i];
        }
    }

    array_sort_quick( help, 0, helpI - 1 ); // 排序不存在arr2中的元素.
    for( i = 0; i < helpI; ++i ) {
        returnArray[returnSize[0]++] = help[i];
    }

    free( help );

    return returnArray;
}

来自英文不好啊

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值