1.调整数组顺序使奇数位于偶数前面
思路:维护两个指针,第一个指针指向第一个数字,从前向后,第二个指针指向数组的最后一个数字,从后往前。如果第一个指针指向的是偶数,第二个指针指向的是奇数,那么就交换这两个数字。终止条件是,第一个指针和第二个指针相遇。
class Solution { public: void reOrderArray(vector<int> &array) { if(array.size()<2) return; int i=0,j=array.size()-1; while(i<j) { while(i<j&&!isEven(array[i])) i++;//定位第一个偶数 while(i<j&&isEven(array[j])) j--;//定位第一个奇数 if(i<j) { int temp=array[i]; array[i]=array[j]; array[j]=temp; } } } bool isEven(int n) { return(n&1)==0; } };
如果顺序不可以改变呢?
class Solution { public: void reOrderArray(vector<int> &array) { int len=array.size(); for(int i=0;i<len;i++) { for(int j=len-1;j>i;j--) { if(array[j]%2==1&&array[j-1]%2==0) { swap(array[j-1],array[j]); } } } /*新建一个数组 vector<int> result; int num=array.size(); for(int i=0;i<num;i++) { if(array[i]%2==1) result.push_back(array[i]); } for(int j=0;j<num;j++) { if(array[j]%2==0) result.push_back(array[j]); } array=result;*/ } };
2.链表的倒数第k个节点
思路:维护两个指针,第一个指针从头结点开始先向前走k-1步,然后从第k步开始,第二个指针也开始从链表的头指针开始遍历,当第一个指针走到尾结点时,第二个指针到达倒数第k个节点。(注意鲁棒性,链表可能为空,k可能为0,可能不存在倒数第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==nullptr||k==0) return nullptr;//特殊情况一· ListNode* p1=pListHead; ListNode* p2=nullptr; for(int i=0;i<k-1;i++) { if(p1->next!=nullptr) p1=p1->next; else return nullptr;//特殊情况二 } p2=pListHead; while(p1->next!=nullptr) { p2=p2->next; p1=p1->next; } return p2; } };
3.链表中环的入口节点
思路:如何判断有环?定义快慢指针,快指针一次走两步,慢指针一次走一步,如果快的追上了慢的,那么代表有环。如何找到环的入口?如果链表的环上面有n个节点,维护两个指针,第一个先走n步,然后第二个节点开始走,二者相遇的节点即为环的入口节点。如何找环上有几个节点?快慢指针相遇一定是在环中,从相遇节点出发,当再次回到这个节点时,可以得到环中节点的个数。
/* struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { } }; */ class Solution { public: ListNode* MeetingNode(ListNode* pHead) { if(pHead==nullptr) return nullptr; ListNode* pSlow=pHead->next; if(pSlow==nullptr) return nullptr;//只有一个或没有节点 ListNode* pFast=pSlow->next; while(pFast!=nullptr&&pSlow!=nullptr) { if(pFast==pSlow) return pFast; pSlow=pSlow->next; pFast=pFast->next; if(pFast!=nullptr) pFast=pFast->next; }//注意不要走到空指针 return nullptr; } ListNode* EntryNodeOfLoop(ListNode* pHead) { ListNode* meetingNode=MeetingNode(pHead); if(meetingNode==nullptr) return nullptr; int nodeInLoop=1; ListNode* p1=meetingNode; while(p1->next!=meetingNode) { p1=p1->next; nodeInLoop++; } p1=pHead; for(int i=0;i<nodeInLoop;i++) { p1=p1->next;//先走环的数量步 } ListNode* p2=pHead; while(p1!=p2) { p1=p1->next; p2=p2->next; } } };
方法二:
/* struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { } }; */ class Solution { public: //设置快慢指针,都从链表头出发,快指针每次走两步,慢指针一次走一步,假如有环,一定相遇于环中某点 //(结论1)。接着让两个指针分别从相遇点和链表头出发,两者都改为每次走一步,最终相遇于环入口(结论2)。 ListNode* EntryNodeOfLoop(ListNode* pHead) { ListNode *fast=pHead; ListNode *low=pHead; while(fast!=NULL&&fast->next!=NULL) { fast=fast->next->next; low=low->next; if(fast==low) break; } if(fast==NULL||fast->next==NULL) return NULL; low=pHead; while(low!=fast)//用while更好 { fast=fast->next; low=low->next; } return low; } };
4.反转链表
思路:维护三个指针,分别指向当前遍历的节点,他的前一个和后一个节点。注意翻转后链表的头结点即原链表的尾结点。
/* struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { } };*/ class Solution { public: ListNode* ReverseList(ListNode* pHead) { if(pHead==nullptr||pHead->next==nullptr) return pHead; ListNode *pReversedHead=nullptr;//用于记录最后一个节点 ListNode *pNode=pHead;//当前节点 ListNode *pPrev=nullptr;//当前节点的前一个节点 while(pNode!=nullptr) { ListNode* pNext=pNode->next; if(pNext==nullptr) pReversedHead=pNode;//如果pNode到达尾结点,令此节点等于pNode pNode->next=pPrev; pPrev=pNode; pNode=pNext; } return pReversedHead; } };
方法二:利用堆栈
/* 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;//一个结点或没有,直接返回 stack<ListNode*> rev; ListNode *p=pHead; while(p->next)//把最后一个结点留下 { rev.push(p); p=p->next; } ListNode *head=p;//新的头结点等于原链表的最后一个结点 while(!rev.empty())//尾插法 { p->next=rev.top(); p=p->next; rev.pop(); } p->next=NULL;//最后一个结点指向NULL return head; } };