单链表OJ
一、 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
struct ListNode*head;
if(list1==NULL)
return list2;
if(list2==NULL)
return list1;
struct ListNode*l1=list1;
struct ListNode*l2=list2;
//创建第一个节点
if(list1->val<=list2->val){
head=list1;
l1=list1->next;
}
else{
head=list2;
l2=list2->next;
}
struct ListNode*list=head;
//注意每次链接修改的是 list->next 的指向,规定 head 为新链表的首节点 **********
while(l1 && l2){
if(l1->val<=l2->val){
list->next=l1;
l1=l1->next;
}
else{
list->next=l2;
l2=l2->next;
}
list=list->next;
}
if(l1!=NULL)
list->next=l1;
if(l2!=NULL)
list->next=l2;
return head;
}
二、现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针。
思路
建立两个链表,一个用来保存小于基准值的节点,一个用来保存大于等于基准值的节点,然后将两个链表进行链接,即可不更改原链表中节点的相对位置 ****************************************************
class Partition {
public:
ListNode* partition(ListNode* pHead, int x) {
if(pHead == NULL)
return NULL;
//创建两个链表,一个用来存在小于节点,另一个用来存储大于等于节点
struct ListNode* lessHead, *lessTail,*greaterHead, *greaterTail;
//创建链表表头---------带头结点的链表
lessHead = lessTail = (struct ListNode*)malloc(sizeof(struct ListNode));
greaterHead = greaterTail = (struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode* cur = pHead;
while(cur)
{
//小于x的尾插到lessTail
if(cur->val < x)
{
lessTail->next = cur;
lessTail = lessTail->next;
}
//大于等于x的尾插到greaterTail
else
{
greaterTail->next = cur;
greaterTail = greaterTail->next;
}
cur = cur->next;
}
//链接两个链表
lessTail->next = greaterHead->next;
greaterTail->next = NULL;
//获取表头
pHead = lessHead->next;
free(lessHead);
free(greaterHead);
return pHead;
}
};
三、判断给定链表是否为回文结构(对称)
思路
方法一、首先寻找到给定链表中间的节点,然后从中间节点开始将后半部分节点进行逆置,然后从原链表首节点开始与中间节点(逆置之后的节点)进行一一比对,若节点全部相等则为回文,否则不是回文
方法二、将整个链表进行逆置并保存到一个新的链表中,对比两个链表是否相等
方法三、建立一个新的数组来保存链表中所有节点的值,然后定义两个指针,一个指向首位,一个指向末尾,逐步进行比较*********************************************
//方法一、
bool chkPalindrome(ListNode* A) {
//空链表或只有一个节点时
if(A==NULL || A->next==NULL)
return true;
//将链表后半段逆置
ListNode*slow=A;
ListNode*fast=A;
while(fast && fast->next)
{
slow=slow->next;
fast=fast->next->next;
}
//从 slow 开始进行逆置
ListNode*cur=slow;
ListNode*q=cur->next;
cur->next=NULL;
ListNode*pre=NULL;
while(q){
pre=q->next;
q->next=cur;
cur=q;q=pre;
}
//从 cur 进行比较
slow=A;
while(slow && cur)
{
if(slow->val!=cur->val)
return false;
slow=slow->next;
cur=cur->next;
}
return true;
}
//方法二、
使用一个数组进行保存链表节点内容
int tmp[10000]={0};
ListNode* cur=A;
int count=0;
while(cur)
{
tmp[count++]=cur->val;
cur=cur->next;
}
//前后比较
int left=0;
int right=count-1;
while(left<right)
{
if(tmp[left]==tmp[right]){
++left;--right;
}
else
return false;
}
return true;
}
三、.原地移除数组中所有的元素val,要求时间复杂度为O(N),空间复杂度为O(1)
//方法一、
int removeElement(int* nums, int numsSize, int val){
//首先查找数组中值等于 val 的元素
while(1){
int i=0;
for(;i<numsSize;++i){
if(nums[i]==val)
break;
}
if(i==numsSize)
break; //查找失败
//找到了值等于 val 元素,移动元素----删除
for(int j=i;j<numsSize - 1;++j)
nums[j]=nums[j+1];
numsSize--;
}
return numsSize;
}
//方法二、
int removeElement(int* nums, int numsSize, int val){
int k=0;
for(int i=0;i<numsSize;++i){
if(nums[i]!=val)
nums[k++]=nums[i]; //直接保存不等于 val 的所有元素
}
return k;
}
四、删除排序数组中的重复项。
给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致
int removeDuplicates(int* nums, int numsSize){
//有序数组
//使用快慢指针,慢指针用来标记存在想等元素的第一个元素,快指针记录最后一个相等值元素
int left=0;
int right=1;
while(right<numsSize){
if(nums[left]==nums[right])
right++; //快指针用来指定相等元素的最后一个元素
else{
nums[left+1]=nums[right]; //不相等元素直接覆盖前边相等的元素位置
left++;
right++;
}
}
return left+1; //有效元素的个数
}
五、合并两个有序数组
给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){
// nums1 数组中前 m 个元素有效 ,后 n 个元素全为0
//数组为非递减数组
int k=m + n - 1;
int i=m-1,j=n-1;
while(i >= 0 && j>= 0){
if(nums1[i]>=nums2[j])
nums1[k--]=nums1[i--]; //从后往前进行保存
else
nums1[k--]=nums2[j--];
}
while(i>=0) //保存剩余元素
nums1[k--]=nums1[i--];
while(j>=0)
nums1[k--]=nums2[j--];
}