HRBUXG ACM ---链表

HRBUXG ACM —链表

转圈打印矩阵

    【题目】
给定一个整型矩阵matrix,请按照转圈的方式打印它。
    例如
        1 2 3 4
        5 6 7 8
        9 10 11 12
        13 14 15 16
    打印结果为:1,2,3,4,8,12,16,15,14,13,9,5,6,7,11, 10
    【要求】额外空间复杂度为O(1)。
    核心思想:将矩阵分圈、再循环打印
    设计一个函数,只打印最外圈,这里取最外圈的左上角顶点和左下角顶点的坐标,表示一个子矩阵,按照从外到里的顺序打印每个子矩阵就可以完成转圈打印。

#include<iostream>
#include<stack>
#include<queue>
#include<cstdlib>
#include<limits.h>
using namespace std;
void printEdge(int *matrix[], int tR, int tC, int dR, int dC);
void spiralOrderPrint(int *matrix[],int row,int col){
    int tR=0;
    int tC=0;
    int dR=row-1;
    int dC=col-1;
    while(tR<=dR && tC<=dC) {
        printEdge(matrix, tR++, tC++, dR--,dC--);
    }
}

void printEdge(int *matrix[], int tR, int tC, int dR, int dC){
    if(tR==dR) {
        //子矩阵只有一行时
        for(int i=tC;i<=dC;i++) {
            cout<<matrix[tR][i]<<" ";
        }
    }else if(tC==dC) {
        //子矩阵只有一列时
        for(int i=tR;i<=dR;i++){
            cout<<matrix[i][tC]<<" ";
        }
    }else{
        //一般情况
        int curC=tC;
        int curR=tR;
        while(curC!= dC) {
            cout<<matrix[tR][curC]<<" ";
            curC++;
        }

        while(curR!= dR) {
            cout<<matrix[curR][dC]<<" ";
            curR++;
        }

        while(curC!= tC) {
            cout<<matrix[dR][curC]<<" ";
            curC--;
        }

        while(curR!= tR) {
            cout<<matrix[curR][tC]<<" ";
            curR--;
        }
    }
}

void printMatrix(int *matrix[],int row,int col) {
    for(int i=0;i<row;i++) {
        for(int j=0;j<col;j++) {
            cout<<matrix[i][j]<<"\t";
        }
        cout<<"\n";
    }
}

int main()
{
    int row,col;
    cin>>row>>col;
    int **matrix=(int **)malloc(sizeof(int)*row);
    int *p[row+1];
    for(int i=0;i<row;i++)
    {
        matrix[i]=(int *)malloc(sizeof(int)*col);
        for(int j=0;j<col;j++)
        {
            cin>>matrix[i][j];
        }
    }
    for(int i=0;i<row;i++){
    	p[i]=matrix[i];
	}
    spiralOrderPrint(p,row,col);
}


旋转正方形矩阵

【题目】 给定一个整型正方形矩阵matrix,请把该矩阵调整成 顺时针旋转90度的样子。
【要求】 额外空间复杂度为O(1)。

#include<iostream>
#include<stack>
#include<queue>
#include<cstdlib>
#include<limits.h>
using namespace std;
void rotateEdge(int *m[], int tR, int tC, int dR, int dC);
void rotate(int *matrix[],int row,int col)
{
    int tR = 0;
    int tC = 0;
    int dR = row - 1;0
    int dC = col - 1;
    while (tR < dR)
    {
        rotateEdge(matrix, tR++, tC++, dR--, dC--);
    }
}

void rotateEdge(int *m[], int tR, int tC, int dR, int dC)
{
    int times = dC - tC;
    int tmp = 0;
    for (int i = 0; i != times; i++)
    {
        tmp = m[tR][tC + i];
        m[tR][tC + i] = m[dR - i][tC];
        m[dR - i][tC] = m[dR][dC - i];
        m[dR][dC - i] = m[tR + i][dC];
        m[tR + i][dC] = tmp;
    }
}

void printMatrix(int *matrix[],int row,int col)
{
    for (int i = 0; i != row; i++)
    {
        for (int j = 0; j != col; j++)
        {
            cout<<matrix[i][j] << " ";
        }
        cout<<endl;
    }
}

int main()
{
    int row,col;
    cin>>row>>col;
    int **matrix=(int **)malloc(sizeof(int)*row);
    int *p[row+1];
    for(int i=0;i<row;i++)
    {
        matrix[i]=(int *)malloc(sizeof(int)*col);
        for(int j=0;j<col;j++)
        {
            cin>>matrix[i][j];
        }
    }
    for(int i=0;i<row;i++){
    	p[i]=matrix[i];
	}
    printMatrix(p,row,col);
    rotate(p,row,col);
    cout<<"========="<<endl;
    printMatrix(p,row,col);
    return 0;
}

反转单向和双向链表

【题目】 分别实现反转单向链表和反转双向链表的函数。

【要求】 如果链表长度为N,时间复杂度要求为O(N),额外空间 复杂度要求为O(1)

#include<iostream>
using namespace std;
const int N = 6;
typedef int DataType;//定义数据类型

typedef struct node{//创建链表node
    DataType data;
    struct node* next;
}LinkedNode,*LinkList;

LinkList CreateList(DataType a[N])//建表函数
{
    LinkedNode* ListHead = new LinkedNode();
    ListHead->data= a[0];
    ListHead->next= NULL;
    for(int i = N - 1;i >= 1;i --)
    {
        LinkedNode* p = new LinkedNode();
        p->data = a[i];
        p->next = ListHead->next;
        ListHead->next = p;
    }
    return ListHead;
}

void PrintList(LinkList ListHead)//实现的一个输出表的函数
{
    if(ListHead == NULL)
        cout<<"This is empty list"<<endl;
    else
        {
            LinkedNode* p = ListHead;
            while(p != NULL)
            {
                cout<<p->data<<" ";
                p = p->next;
            }
            cout<<endl;
        }
}
void RecReverseList(LinkedNode* pCur,LinkList& ListHead)//递归实现表的反转
{
    if( (NULL == pCur) || (NULL == pCur->next) )
    {
        ListHead = pCur;
    }
    else
    {
        LinkedNode* pNext = pCur->next;
        RecReverseList(pNext,ListHead);
        pNext->next = pCur;
        pCur->next= NULL;
    }
}
void UnRecReverseList(LinkList& ListHead)//非递归实现表的反转
{
    if(NULL == ListHead)
        return ;
    LinkedNode *pre,*cur,*nex;
    pre = ListHead;
    cur = pre->next;
    while(cur)
    {
        nex = cur->next;
        cur->next = pre;
        pre = cur;
        cur = nex;
    }
    ListHead->next= NULL;
    ListHead = pre;

}
int main()
{
    int arr[] = {1,2,3,4,5,6};
    LinkedNode* list = CreateList(a);
    PrintList(list);
    LinkedNode* pTemp = list;
    RecReverseList(pTemp,list);
    PrintList(list);
    UnRecReverseList(list);
    PrintList(list);
    return 0;
}

双向链表:先处理前向指针,然后处理后向指针。这些操作都只对当前节点(current),不涉及其它节点。

1.缓存前向指针
2.将后向指针赋值给前向指针
3.将缓存的前者指针,赋值给后向指针
4.当前节点指针移动到下一个待处理节点

#include <iostream>
typedef int DataType;//定义数据类型
typedef struct Node
{
	DataType data;
	Node *next; // 指向下一个节点
	Node *prev; // 指向前一个节点
};

//对链表进行反转
void reverse(Node **head)
{
	Node *temp = NULL;
	Node *current = *head;

	//交换每个节点的后向指针和前向指针
	while (current != NULL)
	{
		temp = current->prev; //temp=1
		current->prev = current->next; //3-->2
		current->next = temp;            //2-->1
		current = current->prev; //3-->2-->1, current变为3,继续往后循环。
	}

	//修改头指针之前,先检测链表是否为空链表,或者只有一个节点的情况
	if (temp != NULL)
		*head = temp->prev;
}

void createDoubleList(Node** head, int newData)
{
	//1. 分配新节点内存
	Node* newNode = new Node;

	//2. 赋值
	newNode->data = newData;

	//3. 将原始头节点做为新节点的后向指针,而前向指针置为NULL
	newNode->next = (*head);
	newNode->prev = NULL;

	//4. 将原始头节点的前向指针置为新的节点
	if ((*head) != NULL)
		(*head)->prev = newNode;

	//5. 将头指针置为新的节点
	(*head) = newNode;
}

void printList(Node *head)
{
	while (head != NULL)
	{
		std::cout<<" "<<head->data<<" ";
		head = head->next;
	}
	std::cout << std::endl;
}


int main()
{
	//初始化链表为:10<->8<->6<->4<->2<->0
	int arr[]={0,2,4,6,8,10};
	Node* head = NULL;
	for(int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
        createDoubleList(&head, arr[i]);
	std::cout << "Original DLL is: ";
	printList(head);
	reverse(&head);
	std::cout << "Reversed DLL is: ";
	printList(head);
	return 0;
}

“之”字形打印矩阵

【题目】 给定一个矩阵matrix,按照“之”字形的方式打印这个矩阵,例如:

1 2 3 4
5 6 7 8
9 10 11 12
“之”字形打印的结果为:1,2,5,9,6,3,4,7,10,11, 8,12
【要求】 额外空间复杂度为O(1)。

#include<iostream>
#include<string>
#include<queue>
#include<cstdlib>
#include<stdexcept>//标准异常库
using namespace std;


void printLevel(int *m[], int tR, int tC, int dR, int dC,bool f);
void printMatrixZigZag(int *matrix[],int row,int col)
{
    int tR = 0,tC = 0,dR = 0,dC = 0;
    int endR = row - 1;
    int endC = col - 1;
    bool fromUp = false;
    while (tR != endR + 1)
    {
        printLevel(matrix, tR, tC, dR, dC, fromUp);
        tR = tC == endC ? tR + 1 : tR;
        tC = tC == endC ? tC : tC + 1;
        dC = dR == endR ? dC + 1 : dC;
        dR = dR == endR ? dR : dR + 1;
        fromUp = !fromUp;
    }
    cout<<endl;
}

void printLevel(int *m[], int tR, int tC, int dR, int dC,bool f)
{
    if (f)
    {
        while (tR != dR + 1)
        {
            cout<<m[tR++][tC--]<<" ";
        }
    }
    else
    {
        while (dR != tR - 1)
        {
            cout<<m[dR--][dC++]<<" ";
        }
    }
}

int main()
{
    int row,col;
    cin>>row>>col;
    int **matrix=(int **)malloc(sizeof(int)*row);
    int *p[row+1];
    for(int i=0;i<row;i++)
    {
        matrix[i]=(int *)malloc(sizeof(int)*col);
        for(int j=0;j<col;j++)
        {
            cin>>matrix[i][j];
        }
    }
    for(int i=0;i<row;i++){
    	p[i]=matrix[i];
	}
    printMatrixZigZag(p,row,col);
    return 0;
}

在行列都排好序的矩阵中找数

【题目】 给定一个有N*M的整型矩阵matrix和一个整数K, matrix的每一行和每一列都是排好序的。实现一个函数,判断K 是否在matrix中。
例如:
0 1 2 5
2 3 4 7
4 4 4 8
5 7 7 9
如果K为7,返回true;如果K为6,返回false。
【要求】 时间复杂度为O(N+M),额外空间复杂度为O(1)。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;

bool isContains(int *matrix[], int Row,int Col,int K) {
    int row = 0;
    int col = Col - 1;
    while (row < Row && col > -1) {
        if (matrix[row][col] == K) {
            return true;
        } else if (matrix[row][col] > K) {
            col--;
        } else {
            row++;
        }
    }
    return false;
}

int main() {
    int row,col,K;
    cin>>row>>col;
    int **matrix=(int **)malloc(sizeof(int)*row);
    int *p[col+1];
    for(int i=0;i<row;i++)
    {
        matrix[i]=(int *)malloc(sizeof(int)*col);
        for(int j=0;j<col;j++)
        {
            cin>>matrix[i][j];
        }
    }
    for(int i=0;i<row;i++)
    {
        p[i]=matrix[i];
    }
    cin>>K;
    cout<<(isContains(p, row,col,K)?"Yes":"No");
}

打印两个有序链表的公共部分

【题目】 给定两个有序链表的头指针head1和head2,打印两个 链表的公共部分。

#include <iostream>
#include <string>
using namespace std;

struct Node {
    int value;
    Node *next;
};

Node *add_Node(Node *head, int value) {
    Node *new_Node = new Node();
    new_Node -> value = value;
    new_Node -> next = NULL;
    Node *p_Node = new Node();
    p_Node = head;
    if(head == NULL)
        head = new_Node;
    else{
        while(p_Node -> next != NULL) {
            p_Node = p_Node -> next;
        }
        p_Node -> next = new_Node;
    }
    return head;
}

void print_common_part(Node *head1, Node *head2) {
    while(head1 != NULL && head2 != NULL) {
    if(head1 -> value < head2 -> value)
        head1 = head1 -> next;
    else if(head1 -> value > head2 -> value)
        head2 = head2 -> next;
    else {
        cout << head1 -> value << ' ';
        head1 = head1 -> next;
        head2 = head2 -> next;
        }
    }
}

int main() {
    Node *head1 = NULL;
    Node *head2 = NULL;
    string str, str_s;
    cout << "please input the data of list1!" << endl;
    getline(cin, str);
    while(str.find(' ', 0) != string :: npos) {
    head1 = add_Node(head1, atoi(str.substr(0, str.find(' ', 0)).c_str()));
        str.erase(0, str.find(' ', 0) + 1);
    }
    head1 = add_Node(head1, atoi(str.c_str()));
    cout << "please input the data of list2!" << endl;
    getline(cin, str);
    while(str.find(' ', 0) != string :: npos) {
        head2 = add_Node(head2, atoi(str.substr(0, str.find(' ', 0)).c_str()));
        str.erase(0, str.find(' ', 0) + 1);
    }
    head2 = add_Node(head2, atoi(str.c_str()));
    cout << "the common part is: " << endl;
    print_common_part(head1, head2);
    return 0;
}

判断一个链表是否为回文结构

【题目】 给定一个链表的头节点head,请判断该链表是否为回文结构。
例如:
1->2->1,返回true。 1->2->2->1,返回true。
15->6->15,返回true。 1->2->3,返回false。
进阶: 如果链表长度为N,时间复杂度达到O(N),额外空间复杂 度达到O(1)。

#include <iostream>
#include <string>
#include<stack>
using namespace std;

struct node {
    int value;
    node *next;
};

node *add_node(node *head, int value) {
    node *new_node = new node();
    new_node -> value = value;
    new_node -> next = NULL;
    node *p_node = new node();
    p_node = head;
    if(head == NULL)
        head = new_node;
    else {
        while(p_node -> next != NULL) {
            p_node = p_node -> next;
        }
        p_node -> next = new_node;
    }
    return head;
}

// need n extra space
bool isPalindrome1(node *head) {
    stack<node> s;
    node *cur = head;
    while (cur != NULL) {
        s.push(*cur);
        cur = cur->next;
    }
    while (head != NULL) {
        if (head->value != s.top().value) {
            return false;
        }
        head = head->next;
        s.pop();
    }
    return true;
}

// need n/2 extra space
bool isPalindrome2(node *head) {
    if (head == NULL || head->next == NULL) {
        return true;
    }
    node *right = head->next;
    node *cur = head;
    while (cur->next != NULL && cur->next->next != NULL) {
        right = right->next;
        cur = cur->next->next;
    }
    stack<node> s;
    while (right != NULL) {
        s.push(*right);
        right = right->next;
    }
    while (!s.empty()) {
        if (head->value != s.top().value) {
            return false;
        }
        head = head->next;
        s.pop();
    }
    return true;
}

// need O(1) extra space
bool isPalindrome3(node *head) {
    if (head == NULL || head->next == NULL) {
        return true;
    }
    node *n1 = head;
    node *n2 = head;
    while (n2->next != NULL && n2->next->next != NULL) { // find mid node
        n1 = n1->next; // n1 -> mid
        n2 = n2->next->next; // n2 -> end
    }
    n2 = n1->next; // n2 -> right part first node
    n1->next = NULL; // mid.next -> null
    node *n3 = NULL;
    while (n2 != NULL) { // right part convert
        n3 = n2->next; // n3 -> save next node
        n2->next = n1; // next of right node convert
        n1 = n2; // n1 move
        n2 = n3; // n2 move
    }
    n3 = n1; // n3 -> save last node
    n2 = head;// n2 -> left first node
    bool res = true;
    while (n1 != NULL && n2 != NULL) { // check palindrome
        if (n1->value != n2->value) {
            res = false;
            break;
        }
        n1 = n1->next; // left to mid
        n2 = n2->next; // right to mid
    }
    n1 = n3->next;
    n3->next = NULL;
    while (n1 != NULL) { // recover list
        n2 = n1->next;
        n1->next = n3;
        n3 = n1;
        n1 = n2;
    }
    return res;
}

void printLinkedList(node *n1) {
    cout<<"Linked List: ";
    while (n1!= NULL) {
        cout<<n1->value << " ";
        n1 = n1->next;
    }
    cout<<endl;
}

int main() {


    node *list=NULL;
    list=add_node(list,1);
    list=add_node(list,2);
    list=add_node(list,2);
    list=add_node(list,1);
    printLinkedList(list);
    cout<<isPalindrome1(list) <<" | ";
    cout<<isPalindrome2(list) << " | ";
    cout<<isPalindrome3(list) <<" | "<<endl;
    printLinkedList(list);

}


将单向链表按某值划分成左边小、中间相等、右边大的形式

【题目】 给定一个单向链表的头节点head,节点的值类型是整型,再给定一个 整数pivot。实现一个调整链表的函数,将链表调整为左部分都是值小于 pivot 的节点,中间部分都是值等于pivot的节点,右部分都是值大于 pivot的节点。 除这个要求外,对调整后的节点顺序没有更多的要求。

进阶: 在原问题的要求之上再增加如下两个要求。 在左、中、右三个部分的内部也做顺序要求,要求每部分里的节点从左 到右的 顺序与原链表中节点的先后次序一致.
【要求】如果链表长度为N,时间复杂度请达到O(N),额外空间复杂度请达到O(1)。

有问题
#include <iostream>
#include <string>
#include<stack>
#include<cstdlib>
using namespace std;

struct Node
{
    int value;
    Node *next;
};
void arrPartition(Node *nodeArr[], int row,int pivot);
void swap_Node(Node *nodeArr[], int a, int b);
Node *add_node(Node *head, int value)
{
    Node *new_node = new Node();
    new_node -> value = value;
    new_node -> next = NULL;
    Node *p_node = new Node();
    p_node = head;
    if(head == NULL)
        head = new_node;
    else
    {
        while(p_node -> next != NULL)
        {
            p_node = p_node -> next;
        }
        p_node -> next = new_node;
    }
    return head;
}


Node *listPartition1(Node *head, int pivot)
{
    if (head == NULL)
    {
        return head;
    }
    Node *cur = head;
    int i = 0;
    while (cur != NULL)
    {
        i++;
        cur = cur->next;
    }
    int row=i;
    Node *nodeArr[row+1] ;
    cur = head;
    for (i = 0; i != sizeof(nodeArr)/sizeof(nodeArr[0]); i++)
    {
        nodeArr[i] = cur;
        cur = cur->next;
    }
    arrPartition(nodeArr, row ,pivot);
    for (i = 1; i != sizeof(nodeArr)/sizeof(nodeArr[0]); i++)
    {
        nodeArr[i - 1]->next = nodeArr[i];
    }
    nodeArr[i - 1]->next = NULL;
    return nodeArr[0];
}

void arrPartition(Node *nodeArr[],int row, int pivot)
{
    int small = -1;
    int big = row;
    int index = 0;
    while (index != big)
    {
        if (nodeArr[index]->value < pivot)
        {
            swap_Node(nodeArr, ++small, index++);
        }
        else if (nodeArr[index]->value == pivot)
        {
            index++;
        }
        else
        {
            swap_Node(nodeArr, --big, index);
        }
    }
}

void swap_Node(Node *nodeArr[], int a, int b)
{
    Node *tmp = nodeArr[a];
    nodeArr[a] = nodeArr[b];
    nodeArr[b] = tmp;
}

Node *listPartition2(Node *head, int pivot)
{
    Node *sH = NULL; // small head
    Node *sT = NULL; // small tail
    Node *eH = NULL; // equal head
    Node *eT = NULL; // equal tail
    Node *bH = NULL; // big head
    Node *bT = NULL; // big tail
    Node *next = NULL; // save next node
    // every node distributed to three lists
    while (head != NULL)
    {
        next = head->next;
        head->next = NULL;
        if (head->value < pivot)
        {
            if (sH == NULL)
            {
                sH = head;
                sT = head;
            }
            else
            {
                sT->next = head;
                sT = head;
            }
        }
        else if (head->value == pivot)
        {
            if (eH == NULL)
            {
                eH = head;
                eT = head;
            }
            else
            {
                eT->next = head;
                eT = head;
            }
        }
        else
        {
            if (bH == NULL)
            {
                bH = head;
                bT = head;
            }
            else
            {
                bT->next = head;
                bT = head;
            }
        }
        head = next;
    }
    // small and equal reconnect
    if (sT != NULL)
    {
        sT->next = eH;
        eT = eT == NULL ? sT : eT;
    }
    // all reconnect
    if (eT != NULL)
    {
        eT->next = bH;
    }
    return sH != NULL ? sH : eH != NULL ? eH : bH;
}

void printLinkedList(Node *node)
{
    cout<<"Linked List: ";
    while (node != NULL)
    {
        cout<<node->value << " ";
        node = node->next;
    }
    cout<<endl;
}

int main()
{
    Node *listHead1=NULL,*listHead2=NULL;

    listHead1=add_node(listHead1,6);
    listHead1=add_node(listHead1,9);
    listHead1=add_node(listHead1,5);
    listHead1=add_node(listHead1,4);
    listHead1=add_node(listHead1,1);
    listHead1=add_node(listHead1,2);
    listHead1=add_node(listHead1,1);
    listHead1=add_node(listHead1,5);

    listHead2=add_node(listHead2,6);
    listHead2=add_node(listHead2,9);
    listHead2=add_node(listHead2,5);
    listHead2=add_node(listHead2,4);
    listHead2=add_node(listHead2,1);
    listHead2=add_node(listHead2,2);
    listHead2=add_node(listHead2,1);
    listHead2=add_node(listHead2,5);
    printLinkedList(listHead1);
    printLinkedList(listHead2);
    //listHead2 = listPartition1(listHead2, 4);
    listHead1 = listPartition2(listHead1, 5);
    printLinkedList(listHead1);
    printLinkedList(listHead2);
    return 0;
}

复制含有随机指针节点的链表

【题目】 一种特殊的链表节点类描述如下:
struct Node
{
int value;
Node *next;
Node *rand;
};
       Node类中的value是节点值,next指针和正常单链表中next指针的意义一样,都指向下一个节点,rand指针是Node类中新增的指针,这个指针可能指向链表中的任意一个节点,也可能指向null。
       给定一个由Node节点类型组成的无环单链表的头节点head,请实现一个函数完成这个链表中所有结构的复制,并返回复制的新链表的头节点。        进阶:不使用额外的数据结构,只用有限几个变量,且在时间复杂度为O(N)内完成原问题要实现的函数。

/*
 *文件名:listWithRand_copy.cpp
 *作者:
 *摘要:复制含有随机指针节点的链表
 */

#include <iostream>
#include <hash_map>

using namespace std;
using namespace __gnu_cxx;

struct Node
{
    int value;
    Node *next;
    Node *rand;
};

//使用hash_map所需要的hash函数
struct hash_Node
{
    size_t operator() (const Node &node) const
    {
        return node.value;
    }
};

//使用hash_map所需要的比较函数
struct compare_Node
{
    bool operator() (const Node &n1,const Node &n2) const
    {
        return n1.value == n2.value && n1.next == n2.next && n1.rand == n2.rand;
    }
};

//使用hash_map解决问题
Node* copyListWithRand1(Node *head)
{
    hash_map<Node,Node,hash_Node,compare_Node> map;
    Node *cur = head;
    while(NULL != cur)
    {
        Node *ptr = new Node;
        ptr->value = cur->value;
        ptr->next = NULL;
        ptr->rand = NULL;
        map[*cur] = *ptr;    //一一对应的关系
        cur = cur->next;
    }
    cur = head;
    while(NULL != cur)
    {
        map[*cur].next = cur->next;
        map[*cur].rand = cur->rand;
        cur = cur->next;
    }
    return &map[*head];
}

Node* copyListWithRand2(Node *head)
{
    if(NULL == head)
        return NULL;
    Node *cur = head;
    Node *next = NULL;
    while(NULL != cur)
    {
        next = new Node;
        next->value = cur->value;
        next->next = cur->next;
        next->rand = NULL;
        cur->next = next;
        cur = next->next;
    }

    cur = head;
    Node *curCopy = NULL;
    while(NULL != cur)    //复制rand
    {
        next = cur->next->next;
        curCopy = cur->next;
        curCopy->rand = NULL != cur->rand ? cur->rand->next : NULL;
        cur = next;
    }

    Node *res = head->next;
    cur = head;
    while(NULL != cur)
    {
        next = cur->next->next;
        curCopy = cur->next;
        cur->next = next;
        curCopy->next = NULL != next ? next->next : NULL;
        cur = next;
    }
    return res;
}

void printListWithRand(Node *head)
{
    while(NULL != head)
    {
        if(NULL != head->rand)
            cout << head->value << " rand is: " << head->rand->value << endl;
        else
            cout << head->value << " rand is: NULL " << endl;

        if(NULL != head->next)
            cout << head->value << " next is: " << head->next->value << endl;
        else
            cout << head->value << " next is: NULL " << endl;
        head = head->next;
    }
}

int main()
{
    Node *head = NULL;
    Node *ptr = NULL;

    for(int i =0;i<4;i++)//构造链表
    {
        if(NULL == head)
        {
            head = new Node;
            head->value = i;
            head->next = NULL;
            head->rand = NULL;
            ptr = head;
            continue;
        }
        ptr->next = new Node;
        ptr->rand = ptr->next;
        ptr = ptr->next;
        ptr->value = i;
        ptr->next = NULL;
        ptr->rand = NULL;
    }

    cout << "before copy:" << endl;
    printListWithRand(head);

    cout << "Using hash_map to copy:" << endl;
    ptr = copyListWithRand1(head);
    printListWithRand(ptr);

    cout << "Using advanced algorithm to copy:" << endl;
    ptr = copyListWithRand2(head);
    printListWithRand(ptr);
    return 0;
}

两个单链表相交的一系列问题

【题目】 在本题中,单链表可能有环,也可能无环。给定两个单链表的头节点head1和head2,这两个链表可能相交,也可能不相交。
请实现一个函数,如果两个链表相交,请返回相交的第一个节点;如果不相交,返回null 即可。
要求:如果链表1的长度为N,链表2的长度为M,时间复杂度请达到 O(N+M),额外空间复杂度请达到O(1)。

#include <iostream>
using namespace std;

struct Node
{
    int value;
    Node *next;
};
Node *getLoopNode(Node *head);
Node *noLoop(Node *head1, Node *head2);
Node *bothLoop(Node *head1, Node *loop1, Node *head2, Node *loop2);
Node *getIntersectNode(Node *head1, Node *head2);
Node *add_node(Node *head, int value)
{
    Node *new_node = new Node();
    new_node -> value = value;
    new_node -> next = NULL;
    Node *p_node = new Node();
    p_node = head;
    if(head == NULL)
        head = new_node;
    else
    {
        while(p_node -> next != NULL)
        {
            p_node = p_node -> next;
        }
        p_node -> next = new_node;
    }
    return head;
}

Node *getIntersectNode(Node *head1, Node *head2)
{
    if (head1 == NULL || head2 == NULL)
    {
        return NULL;
    }
    Node *loop1 = getLoopNode(head1);
    Node *loop2 = getLoopNode(head2);
    if (loop1 == NULL && loop2 == NULL)
    {
        return noLoop(head1, head2);
    }
    if (loop1 != NULL && loop2 != NULL)
    {
        return bothLoop(head1, loop1, head2, loop2);
    }
    return NULL;
}
/**
 *
 * 获取环的入口节点
 */
Node *getLoopNode(Node *head)
{
    if (head == NULL || head->next == NULL || head->next->next == NULL)
    {
        return NULL;
    }
    Node *n1 = head->next; // n1 -> slow
    Node *n2 = head->next->next; // n2 -> fast
    while (n1 != n2)
    {
        if (n2->next == NULL || n2->next->next == NULL)
        {
            return NULL;
        }
        n2 = n2->next->next;
        n1 = n1->next;
    }
    n2 = head; // n2 -> walk again from head
    while (n1 != n2)
    {
        n1 = n1->next;
        n2 = n2->next;
    }
    return n1;
}
/**
 * 两个无环链表
 *
 */
Node *noLoop(Node *head1, Node *head2)
{
    if (head1 == NULL || head2 == NULL)
    {
        return NULL;
    }
    Node *cur1 = head1;
    Node *cur2 = head2;
    int n = 0;
    while (cur1->next != NULL)
    {
        n++;
        cur1 = cur1->next;
    }
    while (cur2->next != NULL)
    {
        n--;
        cur2 = cur2->next;
    }
    if (cur1 != cur2)
    {
        return NULL;
    }
    cur1 = n > 0 ? head1 : head2;
    cur2 = (cur1 == head1 ? head2 : head1);
    n = (n>0?n:-n);
    while (n != 0)
    {
        n--;
        cur1 = cur1->next;
    }
    while (cur1 != cur2)
    {
        cur1 = cur1->next;
        cur2 = cur2->next;
    }
    return cur1;
}
/**
 * 两个有环链表
 * @param head1 第一个链表的头节点
 * @param loop1 第一个链表的入环节点
 * @param head2 第二个链表的头节点
 * @param loop2 第二个链表的入环节点
 * @return Node 两个链表第一次相交的节点
 */
Node *bothLoop(Node *head1, Node *loop1, Node *head2, Node *loop2)
{
    Node *cur1 = NULL;
    Node *cur2 = NULL;
    if (loop1 == loop2)
    {
        cur1 = head1;
        cur2 = head2;
        int n = 0;
        while (cur1 != loop1)
        {
            n++;
            cur1 = cur1->next;
        }
        while (cur2 != loop2)
        {
            n--;
            cur2 = cur2->next;
        }
        cur1 = (n > 0 ? head1 : head2);
        cur2 = (cur1 == head1 ? head2 : head1);
        n = (n>0?n:-n);
        while (n != 0)
        {
            n--;
            cur1 = cur1->next;
        }
        while (cur1 != cur2)
        {
            cur1 = cur1->next;
            cur2 = cur2->next;
        }
        return cur1;
    }
    else
    {
        cur1 = loop1->next;
        while (cur1 != loop1)
        {
            if (cur1 == loop2)
            {
                return loop1;
            }
            cur1 = cur1->next;
        }
        return NULL;
    }
}

int main()
{
    // 1->2->3->4->5->6->7->null
    Node *head1;
    head1=add_node(head1,1);
    head1=add_node(head1,2);
    head1=add_node(head1,3);
    head1=add_node(head1,4);
    head1=add_node(head1,5);
    head1=add_node(head1,6);
    head1=add_node(head1,7);

    // 0->9->8->6->7->null
    Node *head2;
    head2=add_node(head2,0);
    head2=add_node(head2,9);
    head2=add_node(head2,8);
    head2->next->next->next = head1->next->next->next->next->next; // 8->6
    cout<<(getIntersectNode(head1, head2)->value);

    // 1->2->3->4->5->6->7->4->->->
    Node *head3;
    head3=add_node(head3,1);
    head3=add_node(head3,2);
    head3=add_node(head3,3);
    head3=add_node(head3,4);
    head3=add_node(head3,6);
    head3=add_node(head3,7);
    head3->next->next->next->next->next->next = head3->next->next->next; // 7->4

    // 0->9->8->2->->->
    Node *head4;
    head4=add_node(head4,0);
    head4=add_node(head4,9);
    head4=add_node(head4,8);
    head4->next->next->next = head3->next; // 8->2
    cout<<(getIntersectNode(head3, head4)->value);

    // 0->9->8->6->4->5->6->->
    Node *head5;
    head5=add_node(head5,0);
    head5=add_node(head5,9);
    head5=add_node(head5,8);
    head5->next->next->next = head3->next->next->next->next->next; // 8->6
    cout<<(getIntersectNode(head3, head5)->value);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值