话在前:(1)题目描述 (2)解题思路 (3)代码和结果
(1)题目描述:
给你一个长度固定的整数数组 arr,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。
注意:请不要在超过该数组长度的位置写入元素。
要求:请对输入的数组 就地 进行上述修改,不要从函数返回任何东西。
示例 1:
输入:[1,0,2,3,0,4,5,0]
输出:null
解释:调用函数后,输入的数组将被修改为:[1,0,0,2,3,0,0,4]
示例 2:
输入:[1,2,3]
输出:null
解释:调用函数后,输入的数组将被修改为:[1,2,3]
提示:
1 <= arr.length <= 10000
0 <= arr[i] <= 9
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/duplicate-zeros
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
(2)解题思路
方法1:用循环去遍历零,遇零则先移位后面的数据,再写零到下一个位置。
思考:这是大多数人第一眼的想法,但是我认为这道题考的就是不能这么去做,因为时间几乎就是耗在移位上的,特别是当数据量很大的时候,想想都恐怖!
方法2:先copy原数组,再去选择插入。
思考:细想的话应该是没问题的,但是我不敢细想,因为数据量大了,比如一个T,你去复制???
然后得到最终的方法:
先遍历数组,得到所有零的下标,下标值存在一个index数组中;
再根据零的个数,去决定下一个循环处理的次数,在处理循环中,核心就是计算零在移位后应该的位置(暂不考虑溢出)zero_pos,然后区分zero_pos在原数组末尾的相对位置:
(zero_pos < (arrsize-1) 、zero_pos = (arrsize-1)、zero_pos > (arrsize-1))
最后根据这三种情况去对每个小unit(一个零到下一个零 or 一个零到数组边界)做处理,处理细节见代码吧(看不懂的可以留言,谢谢)
(3)代码和结果//附有完整测试代码,可在本地自测
#include <stdio.h>
void duplicateZeros(int* arr, int arrSize)
{
size_t i, j, count, s1, s2, j_src, tmp_len = 0, zero_pos = 0;
unsigned int index[arrSize];
//memset(index, 0, sizeof(index));
//step1:find the indx of zero
for (j = 0, i = 0; i < arrSize; ++i){
if (arr[i] == 0)
index[j++] = i;
}
int arrlen = arrSize - 1;
//step2:change data from tail to head
j_src = j;
for ( ; j > 0; --j){
zero_pos = ((j - 1) + index[j - 1]);
if ( zero_pos == (arrlen)){//the zero on the tail
arr[arrlen] = 0;
}
else{
if( zero_pos > (arrlen) ){//the zero out of tail
if( ((j-1) > 0) && ( ((j - 2) + index[j - 2]) < (arrlen)) ){
tmp_len = (arrlen ) - ((j - 2) + index[j - 2]) - 1;
}
}
else{//the zero in tail
if( tmp_len > 0 ){
count = tmp_len;
tmp_len = 0;
}
else{
if( j == j_src )
count = arrSize - index[j-1] - 1;
else
count = index[j] - index[j-1] - 1;
}
s1 = zero_pos + 2 + count - 1;
s2 = 1 + index[j-1] + count - 1;
if( s1 > (arrlen) ){
count = count - (s1 - (arrlen));
s1 = zero_pos + 2 + count - 1;
s2 = 1 + index[j-1] + count - 1;
}
for ( i = 0; i < count; i++){
arr[s1--] = arr[s2--];
}
arr[zero_pos] = 0;
arr[zero_pos+1] = 0;
}
}
}
}
unsigned int arr[] = {1, 2, 0, 3, 0, 4, 5, 0, 6, 7};
unsigned int arr_ex[] = {1, 0, 2, 3, 0, 4, 5, 0};
unsigned int arr_ex2[] = {8, 5, 0, 9, 0, 3, 4, 7};
#define dest_arr arr_ex2
int main(void)
{
size_t i;
printf_s("the arrary of int:\n");
size_t count = sizeof(dest_arr) / sizeof(int);
for (i = 0; i < count; i++){
printf_s("%d ", dest_arr[i]);
}
printf_s("\n");
printf_s("after dup_zero:\n");
duplicateZeros(dest_arr, count);
for (i = 0; i < count; i++){
printf_s("%d ", dest_arr[i]);
}
return 0;
}