线性表--删除顺序表中为x的元素

题目要求:

删除顺序表中为x的元素,保留其他元素,时间复杂度不超过O(n),空间复杂度不超过O(1)

方法一:重建法

设置k,k个保留元素放到新的顺序表A1,依次把元素插进A

1.k记录保留的元素个数

2.保留新的元素插入A1的物理位序

 

代码实现:

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
//已知长度为n的线性表A采用顺序存储结构,
//编写一个时间复杂度为O(n)、空间复杂度为O(1)的算法,
//该算法删除线性表中所有值为x的数据元素。


//1.重建法
//重新设立一个顺序表,内部储存数据为除x外的有效数据
typedef int ElemType;

typedef struct Sqlist
{
	ElemType length;
	ElemType data[100];
}SqList;

void delnode1(SqList** A,ElemType x)
{
	int k = 0, i;//k记录值不等于x的元素个数
	for (i=0;i<(*A)->length;i++)
	{
		if ((*A)->data[i]!=x)//若当前元素不为x,将其插入新顺序表A中
		{
			(*A)->data[k] =(*A)->data[i];
			k++;//不等于x的元素增加1
		}
	}
	(*A)->length = k;
}

方法二:快慢指针法

通过前后两个指针,第一个指针用于判断元素的值与x的关系

不为x则将快指针j的值传给i,为x则向后移动,不进行赋值操作

代码实现:

//2.快慢指针法

void delall(SqList* A, int x)
{
	int i = 0, j;
	while (i < A->length && A->data[i] != x)//找到第一个元素为x的位置i
		i++;
	for (j = i + 1; j < A->length; j++)    //    i+1 =< j < A->length
		if (A->data[j] != x)
		{
			A->data[i] = A->data[j];
			i++;
		}
	A->length = i;
}

方法三:移位法

通过将后面的非x元素前移,取代x

代码实现:

//3.移位法
void delnode2(SqList **A,ElemType x)
{
	int p = 0, i = 0;
	//p的含义:p为顺序表A中空出来的位置数目,后续保留元素前方的空位数,即前移位数
	//①p记录删除元素个数②保留的新元素前移的位置数
	while (i<((*A)->length))
	{
		if ((*A)->data[i]==x)//当元素值为x时p增加1
		{
			p++;
		}
		else
		{
			(*A)->data[i - p] = (*A)->data[i];//将当前元素不为x时,将其前移p个位置
		}
		i++;
	}
	(*A)->length -= p;//顺序表A的长度递减p
}

27. 移除元素

给你一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

示例 1:
输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。

示例 2:
输入:nums = [0,1,2,2,3,0,4,2], val = 2
输出:5, nums = [0,1,4,0,3]
解释:函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。 

代码实现: 

int removeElement(int* nums, int numsSize, int val)
{
    int left=0;
    for(int i=0;i<numsSize;i++)
    {
        if(nums[i]!=val)
        {
            nums[left]=nums[i];
            left++;
        }
    }
    return left;
}

203. 移除链表元素

题目要求: 

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

示例 1:

输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]

示例 2:

输入:head = [], val = 1
输出:[]

示例 3:

输入:head = [7,7,7,7], val = 7
输出:[]

思路:

思路与前面的题目大致相同,首先设立快慢指针,慢指针p,快指针q。其中p用来设置保存结果的链表,而q用来跨过值为val的节点

这里需要考虑几个问题,如果p最开始的值就为val值,那么需要考虑将头节点向后移动,删去首个节点

还需要考虑如果最后所有元素都迭代完毕了,最后剩下的一个尾结点的值是否为val

代码实现: 

struct ListNode* removeElements(struct ListNode* head, int val)
{
    if(head==NULL)
    {
        return NULL;
    }
    struct ListNode* p=head;
    struct ListNode* q=p->next;
    while(p->next!=NULL)
    {
        if(p->val==val)
        {
            head=q;
            p=q;
            q=q->next;
        }
        else if(q->val!=val)
        {
            p=p->next;
            q=q->next;
        }
        else
        {
            q=q->next;
            p->next=q;
        }
        
    }
    if(p->val==val)
        {
        return NULL;
        }
    return head;
}
  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值