剑指offer(13~15)--调整数组顺序使奇数位于偶数前面--链表中倒数第k个节点--反转链表

版权声明:允许转载,请注明文章出处 https://blog.csdn.net/Vickers_xiaowei/article/details/85880130

13、调整数组顺序使奇数位于偶数前面

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

一个下标找偶数后插到数组

从头到尾找偶数,找到偶数将这个偶数之后的元素依次向前移一位,而把这个偶数放到最后,如果是奇数则跳过。我觉得这个题不难理解,难的是如何判断数组已经符合要求了,也就是循环结束的条件,为了这个循环结束条件,我还定义了一个count变量用来统计已经移动到数组尾部的偶数个数。当下标不小于这个数组长度-count时候结束。
在这里插入图片描述

class Solution {
public:
    void reOrderArray(vector<int> &array) {
        int i=0,end=array.size(),count=0;
        while(i<end-count)
        {
            if((array[i]&1)==0)
            {
                int tmp=array[i];
                for(int j=i;j<end-1;j++)
                    array[j]=array[j+1];
                array[end-1]=tmp;
                count++;
            }
            else
            {
                i++;
            }
        }
    }
};

牛客网链接

还是上面的思路我采用STL的vector的接口做,由于erase存在迭代器失效问题,所以只能采用下标配合迭代器做出来。count用来统计偶数个数,i作用是给迭代器弄个下标。

class Solution {
public:
	void reOrderArray(vector<int> &array) {
		vector<int>::iterator it = array.begin();
		int count = 0, end = array.size(),i = 0;
		while (i<end-count)
		{
			if (((*it) & 1) == 0)
			{
				int tmp = (*it);
				array.erase(it);
				array.push_back(tmp);
				count++;
				it = array.begin();
				i = 0;
			}
			else
			{
				it++;
				i++;
			}
		}
	}
};

牛客网链接

两个下标找奇数前插到偶数之前

在这里插入图片描述
这里虽然可以使用双下标去分别找奇数的偶数,但是找到之后不能直接互换,互换不能保证偶数和偶数原来的相对位置不变。比如第二个状态,当我再次找到偶数2和奇数5时候,如果互换,那么2和4的相对位置就发生了变化。

实际这个题目不管是一个下标还是两个下标,思路差别不大,数组就是这特点,需要整体移动,可是它存储空间相对集中啊,所以数组更适合用于增删较少的场景。

class Solution {
public:
	void reOrderArray(vector<int> &array) {
		int fast = 0, count = 0;
		int end = array.size();
		while (fast<end - count)
		{
			if ((array[fast] & 1) == 0)//fast指向偶数
			{
				count++;
				for (int slow = fast; slow<end; slow++)
				{
					if ((array[slow] & 1) == 1)
					{
						int tmp = array[slow];
						for (int i = slow; i>fast; i--)
						{
							array[i] = array[i-1];
						}
						array[fast] = tmp;
                        fast++;
					}
				}
            }
            else
                fast++;
		}
	}
};

牛客网链接

14、链表中倒数第k个节点

输入一个链表,输出该链表中倒数第k个结点。

准确返回第K的节点

在这里插入图片描述
先遍历一遍统计单链表有多少个节点,分析可知,总的节点-K就是k的下标(把链表当成数组看待)。再遍历一遍,在这个sum-k的位置,返回这个节点。

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
	ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
		int sum = 0;
		ListNode*cur = pListHead;
		while (cur)
		{
			sum++;
			cur = cur->next;
		}
		cur = pListHead;
		int i = 0;//给链表弄个下标
		while (i != sum - k&&cur)
		{
			cur = cur->next;
			i++;
		}
		return cur;
	}
};

牛客网链接

双下标快速准确

定义两个指针,让快指针指向第k个节点,然后快慢指针一起走,等快指针到尾,慢指针就指向倒数第k个节点了。

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        if(pListHead==NULL||k<=0)return NULL;
        ListNode* fast,*slow;
        fast=slow=pListHead;
        while(k--)
        {
            if(fast==NULL)
                return NULL;
            fast=fast->next;
        }
        while(fast!=NULL)
        {
            fast=fast->next;
            slow=slow->next;
        }
        return slow;
    }
};

牛客网链接

15、反转链表

输入一个链表,反转链表后,输出新链表的表头。

就地逆置

在这里插入图片描述

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if(pHead==NULL||pHead->next==NULL)return pHead;
        ListNode*n1,*n2,*n3;
        n1=pHead;
        n2=n1->next;
        n3=n2->next;
        while(n2)
        {
            n2->next=n1;
            n1=n2;
            n2=n3;
            if(n3)
                n3=n3->next;
        }
        pHead->next=NULL;
        pHead=n1;
        return pHead;
    }
};

牛客网链接

借用栈

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        stack<int> s;
        ListNode*cur=pHead;
        while(cur!=nullptr)
        {
            s.push(cur->val);
            cur=cur->next;
        }
        //开始出栈
        cur=pHead;
        while(!s.empty())
        {
            cur->val=s.top();
            s.pop();
            cur=cur->next;
        }
        return pHead;
    }
};

这道题我先前在网上看到有人提出来用头插法做,自己试了好久,最后觉得头插思想真的很不错,但是这道题真的不适合。单链表很难找到尾节点,如果我头插一次都要遍历一遍单链表,就太复杂了。凡是逆置问题都可以用栈来做,简单好操作。

牛客网链接

猜你喜欢

转载自blog.csdn.net/Vickers_xiaowei/article/details/85880130