顺序表的增删查改及OJ练习题
1.顺序表
#include"SeqList.h"
// 顺序表初始化
void SeqListInit(SeqList* psl)
{
assert(psl);
psl->array = NULL;
psl->capicity = psl->size = 0;
}
// 顺序表销毁
void SeqListDestory(SeqList* psl)
{
assert(psl);
free(psl->array);
psl->array = NULL;
psl->capicity = psl->size = 0;
}
// 检查空间,如果满了,进行增容
void CheckCapacity(SeqList* psl)
{
if (psl->capicity == psl->size)
{
size_t newcapicity = psl->capicity == 0 ? 4 : 2 * psl->capicity;
psl->array = realloc(psl->array, newcapicity*sizeof(SLDataType));
psl->capicity = newcapicity;
}
}
// 顺序表打印
void SeqListPrint(SeqList* psl)
{
assert(psl);
for (size_t i = 0; i < psl->size; ++i)
{
printf("%d ", psl->array[i]);
}
printf("\n");
}
// 顺序表尾插
void SeqListPushBack(SeqList* psl, SLDataType x)
{
assert(psl);
CheckCapacity(psl);
psl->array[psl->size] = x;
psl->size++;
}
// 顺序表尾删
void SeqListPopBack(SeqList* psl)
{
assert(psl && psl->size);
psl->size--;
}
// 顺序表头插
void SeqListPushFront(SeqList* psl, SLDataType x)
{
assert(psl);
CheckCapacity(psl);
size_t end = psl->size;
for (; end > 0; --end)
{
psl->array[end] = psl->array[end - 1];
}
psl->array[0] = x;
psl->size++;
}
// 顺序表头删
void SeqListPopFront(SeqList* psl)
{
assert(psl && psl->size);
size_t star = 1;
for (star; star < psl->size; ++star)
{
psl->array[star - 1] = psl->array[star];
}
psl->size--;
}
// 顺序表查找
int SeqListFind(SeqList* psl, SLDataType x)
{
assert(psl);
for (size_t i = 0; i < psl->size; ++i)
{
if (psl->array[i] == x)
return i;
}
return -1;
}
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* psl, size_t pos, SLDataType x)
{
assert(psl);
CheckCapacity(psl);
size_t end = psl->size;
for (; end >= pos; --end)
{
psl->array[end] = psl->array[end - 1];
}
psl->array[pos] = x;
psl->size++;
}
// 顺序表删除pos位置的值
void SeqListErase(SeqList* psl, size_t pos)
{
assert(psl && psl->size);
size_t i = pos + 1;
while (i < psl->size)
{
psl->array[i - 1] = psl->array[i];
i++;
}
psl->size--;
}
2.原地移除数组中所有的元素val,要求时间复杂度为O(N),空间复杂度为O(1)
解题思路:
用双指针,遍历数组,如果遇到值和val值相等则++src,如果值不行等则让src的值覆盖sub,两个指针再加一步,当遍历完数组时剩下的内容和长度满足题意。
int removeElement(int* nums, int numsSize, int val){
int src = 0,sub = 0;
while(src < numsSize)
{
if(nums[src] == val)
++src;
else
nums[sub++] = nums[src++];
}
return sub;
}
3.给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
解题思路:
这道题和上面的题类似,设前后指针后面的指向的值如果和前一个指针指向的值相同则进行删除,让后一个继续走,直到遇到不相同的数字,因为相同值要保留一个,让第二指针所指向不同值赋给第一个指针+1指向的内容即可。
int removeDuplicates(int* nums, int numsSize){
if(nums == NULL||numsSize == 0)
return 0;
int one = 0;
int two = 1;
while(two < numsSize)
{
if(nums[one] == nums[two])
{
two++;
}
else
{
nums[one+1] = nums[two];
one++;
two++;
}
}
return one+1;
}
4.给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。
说明:
初始化 nums1 和 nums2 的元素数量分别为 m 和 n。
你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。
解题思路:
因为两个数组有序如果从前向后排序必然会出现覆盖或者顺序紊乱情况,如果从后向前遍历两个数组则可以有效避免这种情况发生。比较谁的值大就放到数组最后,两个数组依次向前比较,最后可能出现2种情况:
(1)如果nums1中的值比较完成全部插入数组中,剩下nums2的一部分,则将剩余部分继续向前遍历插入数组即可;
(2)相反如果nums2遍历完成剩下nums1,因为现在插入的数组是nums1,剩下的部分就是最小的几个数,所以不用动,本来nums1就是有序的数组。
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){
int len1 = m-1;
int len2 = n-1;
int len = m+n-1;
while(len1 >= 0 && len2 >= 0)
{
nums1[len--] = nums1[len1] > nums2[len2] ? nums1[len1--] : nums2[len2--];
}
while(len2>=0)
{
nums1[len--] = nums2[len2--];
}
}
5.给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
示例 1:
输入: [1,2,3,4,5,6,7] 和 k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右旋转 1 步: [7,1,2,3,4,5,6]
向右旋转 2 步: [6,7,1,2,3,4,5]
向右旋转 3 步: [5,6,7,1,2,3,4]
解题思路:
这个题按照示例逻辑非常容易实现,下面是这个题的另一种思维方式;既然是旋转数组则本质就是数组的逆置,只不过旋转逆置一个而已。
原数组
先逆置numSize-k-1
先逆置numSize-k-1  再逆置numSize-1-----numSize-1部分
最后整体逆置
6.对于非负整数 X 而言,X 的数组形式是每位数字按从左到右的顺序形成的数组。例如,如果 X = 1231,那么其数组形式为 [1,2,3,1]。
给定非负整数 X 的数组形式 A,返回整数 X+K 的数组形式。
解题思路:
让我们逐位将数字加在一起。举一个例子,如果要计算 123 与 912的和。我们顺次计算 3+2、2+1、1+9。任何时候,当加法的结果大于等于 10,我们要将进位的 1 加入下一位的计算中去,所以最终结果等于 1035。我们把它表示成 [1, 2, 3+912]。然后,我们计算3+912=915。5留在当前这一位,将 910/10=91 以进位的形式加入下一位。然后,我们再重复这个过程,计算 [1, 2+91, 5]。我们得到 93,3 留在当前位,将90/10=9 以进位的形式加入下一位。继而又得到 [1+9, 3, 5],重复这个过程之后,最终得到结果 [1, 0, 3, 5]。
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* addToArrayForm(int* A, int ASize, int K, int* returnSize){
int* addRet = (int*)malloc(sizeof(int)*10001);
//第i位
int reti = 0;
//从低位开始相加
int ai = ASize-1;
//进位
int next = 0;
while(ai>=0 || K>0)
{
int x1 = 0;
//如果ai没有越界
if(ai >= 0)
{
x1 = A[ai];
--ai;
}
int x2 = 0;
//如果K大于0,获取K的每一位
if(K > 0)
{
x2 = K % 10;
K = K / 10;
}
//对应位置相加 如果满足进位
int ret = x1 + x2 + next;
if(ret > 9)
{
ret = ret % 10;
next = 1;
}
else
{
next = 0;
}
addRet[reti++] = ret;
}
if(next == 1)
{
addRet[reti++] = 1;
}
Reverse(addRet,0,reti-1);
*returnSize = reti;
return addRet;
}
void Reverse(int* nums,int left,int right)
{
while(left < right)
{
int tmp = nums[left];
nums[left++] = nums[right];
nums[right--] = tmp;
}
}