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