为了将链表搞透,继续分享链表的题,将链表反转,合并两个链表,链表进行循环右移,还有数组的操作,由于篇幅,加上冒泡,最小堆的代码。(很抱歉散乱的上传代码,数组题,逻辑题,链表没清晰区分开)。基本上有的思路很多的 我写了几种实现。
20.反转链表
输入一个链表,反转链表后,输出链表的所有元素
这里改变了链表的结构
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
if(pHead == NULL) return NULL;
if(pHead->next==NULL) return pHead;
ListNode* pri = pHead;
ListNode* cur = pHead->next;
pri->next = NULL;
ListNode* q = NULL;
while(cur->next!=NULL)
{
q = cur;
cur =cur->next;
q->next = pri;
pri=q;
}
cur->next=pri;
return cur;
}
};
21.从尾到头打印链表
输入链表的表头,输出为需要打印的“新链表”的表头
(这里需要用 容器存储每个结点的数据)
1.用上面代码略微改动
修改链表结构:
class Solution {
public:
vector<int> printListFromTailToHead(struct ListNode* head) {
vector<int> list1;
if(head == NULL){
return list1;
}
if(head->next==NULL)
{
list1.push_back(head->val);
return list1;
}
ListNode* pri = head;
ListNode* cur = head->next;
pri->next = NULL;
ListNode* q = NULL;
while(cur->next!=NULL)
{
q = cur;
cur =cur->next;
q->next = pri;
pri=q;
}
cur->next=pri;
while(cur)
{
list1.push_back(cur->val);
cur =cur->next;
}
return list1;
}
};
2.利用栈(出栈时候就是逆序,但栈对内存消耗很大。牛客上时间空间都做限制,通不过,但这是一种方法)
class Solution {
public:
vector<int> printListFromTailToHead(struct ListNode* head) {
vector<int> list1;
if(head == NULL)
return list1;
stack<int> stack1;
while(head)
{
stack1.push(head->val);
head =head->next;
}
while(!stack1.empty()){
list1.push_back(stack1.top());
}
return list1;
}
};
3.不改变链表的结构:
只是逆序输出结点,不产生新表(递归):
//利用vector的函数
vector<int> printListFromTailToHead(struct ListNode* head) {
vector<int> v;
while(head != NULL)
{
v.insert(v.begin(),head->val);
head = head->next;
}
return v;
}
//基本的push_back压入
class Solution {
public:
vector<int> list1;
vector<int> printListFromTailToHead(struct ListNode* head) {
if(head==NULL)
return list1;
list1=printListFromTailToHead(head->next);
list1.push_back(head->val);
return list1;
}
};
22.合并两个排序的链表
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
if(pHead1==NULL)
return pHead2;
if(pHead2==NULL)
return pHead1;
ListNode* pHead=NULL; //保存新的头结点
ListNode* p1=pHead1; //为了写的方便,就将p1.p2替换原来的两个头结点
ListNode* p2=pHead2;
ListNode* pre=pHead1;
ListNode* pT=NULL;
if(p2->val<=p1->val){ //确定头结点
pHead = p2;
p2=p2->next;
pHead->next=p1;
pre = pHead;
}
else{
pHead =p1;
p1=p1->next;
pre =pHead;
}
//将2插入1中
while(p1!=NULL&&p2!=NULL){
if(p2->val<p1->val){
pT=p2;
p2=p2->next;
pre->next=pT;
pT->next=p1;
}
else{
pre=p1;
p1=p1->next;
}
}
if(p1==NULL&&p2!=NULL){
pre->next = p2;
p2=p2->next;
}
if(p2==NULL&&p1!=NULL) {
pre->next = p1;
p1=p1->next;
}
return pHead;
}
};
23.左旋转字符串
(即循环右移字符串)S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。
//思想:比如adcd。先adcdabcd。这样随便哪个位置取4位 cdab,这样的都可以
class Solution {
public:
string LeftRotateString(string str, int n) {
int len = str.length();
if(len == 0) return "";
n = n % len;
str += str; //直接两个相同的串连接,然后位移的位置取原长度的字符串
return str.substr(n, len);
}
};
//利用string类的substr函数求子串,再连接也可以。(不过上面的方法让你很有新的思路)
class Solution {
public:
string LeftRotateString(string str, int n) {
int len = str.length();
if(len == 0) return "";
string str1=str.substr(n,len);
string str2=str.substr(0,n);
string str3 =str1+str2;
return str3;
}
};
24.旋转数组的最小数字(类似上面旋转字符串)
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
//思想:从第二个元素和第一个元素比,因为前面递增的,出现比第一个小的,就是旋转的起始
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
if(rotateArray.size()==0)
return 0;
unsigned long i=0;
for(;i<rotateArray.size();i++){
if(rotateArray[i]<rotateArray[0])
return rotateArray[i];
}
return rotateArray[0];
}
};
//思想:每个数和前面的比,突然比前面的小的, 就是旋转数组的起始数
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
if(rotateArray.size()==0)
return 0;
if(rotateArray.size()==1)
return rotateArray[0];
unsigned long i=0;
for(;i<rotateArray.size();i++)
if(rotateArray[i]>rotateArray[i+1])
return rotateArray[i+1];
return rotateArray[0];
}
};
25.最小的K个数
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
最小堆:
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> result ;
if(k > input.size()) return result;
for(int i = 0; i < k ; i ++){
heapSort(input,i,input.size());
result.push_back(input[i]);
}
return result;
}
};
冒泡(比较慢)取前k个数
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> output;
if(input.size()<=0||k<=0||k>input.size())
return output;
int num=input.size(), i,j,temp=0;
for( i=0;i<num-1;i++)
for( j=0;j<num-1-i;j++){
if(input[j]>input[j+1]){
temp=input[j];
input[j]=input[j+1];
input[j+1]=temp;
}
}
for(int i=0;i<k;i++){
output.push_back(input[i]);
}
return output;
}
};