数据结构链表例题

给定一个链表L,链表中的整数数据是唯一的。
给定一个数组G,G中的数据全是链表L中的数,但是顺序可能是打乱的。
现在要判断G中的数据在对应链表中的数据位置是否是连接上的,并求出链接上的组数。
例如:
L:0->7->2->9->4
G:{0,9,7,4}
结果返回:2,因为{0,7}在L中式连续的,{9,4}在L中是连续的,3个连续或者更多同样算一个。当最后只有一个的情况下是视为一个连续段。




Solution_1:
遍历链表得出数组G中的数据在链表中的位置,然后对位置进行排序,最后判断是每个位置是否是连续的,通过:后-前==1来判断。
typedef struct ListNode * PList;


int numComponents(struct ListNode* head, int* G, int GSize) {
    if(head == NULL)
return 0;
    int *position = (int *)malloc(sizeof(int) * GSize);           //记录数据的实际位置数组
PList temp = (PList)malloc(sizeof(struct ListNode));
temp = head;
int count = 0;
int PosCount = 0;
//找出实际的位置
    for(int i = 0;i < GSize;i++)
{
   while(temp!= NULL)
   {
      if(G[i] == temp->val)
  {
     position[PosCount++] = count;
break;
  }
  temp = temp->next;
  count++;
   }
   count = 0;
   temp = head;
}
//冒泡排序
int intergeTemp;
for(int j = 0;j < GSize-1;j++)
{
   for(int k = 0;k < GSize-j-1;k++)
   {
           if(position[k] > position[k+1])
           {
               intergeTemp = position[k];
               position[k] = position[k+1];
               position[k+1] = intergeTemp;
           }
   }
}
int result = 1;
for(int i = 0;i < GSize-1;i++)
{
    if(position[i+1] - position[i] != 1)
          result++;

return result;
}
//判断空绝对不能少!




------------------------------------------------------------
Solution 2:
通过遍历链表L的每个数据直接判断数组G中的数据是否连接在一起。
每当遍历到一个L中的数据我们就在数组中查找,如果未查找到则说明出现断点,那么连续的分组数目就可以加一
同时为了避免本来未在G中的数据而在L中出现,从而产生问题,设置一个标志量来记录当前状态,是否是出于已经在判断连续的状态:
例如:
L:0->1->2->3->4->5->6->7->8
G:{0,5,6,8}
如果没有标志量则1,2,3,4都会认为出现断点
int numComponents(struct ListNode* head, int* G, int GSize) {
    if(head == NULL)
return 0;
PList temp = head;
int result = 1;
bool flag = false,IsBegin = false;
int GCount = 0;                         //记录G数组的使用数据的个数
while(temp != NULL)
{
    for(int i = 0;i < GSize;i++)
{
    if(temp->val == G[i])
{
flag = true;
IsBegin = true;
GCount++;
if(GCount == GSize)
return result;
break;
}
}
if(!flag && IsBegin)
{
   result++;
   IsBegin = false;
}
else
   flag = false;
temp = temp->next;
}
return result;

}



----------------------------------------例题2-----------------------------------------------------------------------------------

Given a singly linked list, group all odd nodes together followed by the even nodes. Please note here we are talking about the node number and not the value in the nodes.


You should try to do it in place. The program should run in O(1) space complexity and O(nodes) time complexity.




Solution:
struct ListNode* oddEvenList(struct ListNode* head) {
    if(head == NULL)
        return NULL;
    //第二队队首
    PList SecondHead = head->next;
PList p = head;                   //第一队队尾
PList q = head->next;             //第二队队尾
while(p->next != NULL && q->next != NULL)
{
    p->next = q->next;
p = p->next;
q->next = p->next;
q = q->next;
}
p->next = SecondHead;
return head;
}

//空链表的判断一定是需要的。


----------------------------------------------------例题3--------------------------------------------------------

Write a program to find the node at which the intersection of two singly linked lists begins.
a1->a2->c1->c2->c3
b1->b2->b3->c1->c2->c3
answer: c1




Solution 1:
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    PList TempHeadA = (PList)malloc(sizeof(struct ListNode));
    TempHeadA = headA;
    PList TempHeadB = (PList)malloc(sizeof(struct ListNode));
    TempHeadB = headB;
    while(TempHeadA != NULL)
    {
         while(TempHeadB != NULL)
         {
             if(TempHeadA == TempHeadB)
                return TempHeadA;
             TempHeadB = TempHeadB->next;
         }
         TempHeadA = TempHeadA->next;
         TempHeadB = headB;
    }
    return NULL;
}


Solution 2:
利用双指针走两个链表,设L1的私有段长度为x1,L2私有段长度为x2,共有段为y。
可以得:
x1 + y + x2 + y
x2 + y + x1 + y
可以看出在前三个部分就可以让指针置于同一起跑点,所以有:
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    if(headA == NULL || headB == NULL)
        return NULL;
    PList TempA = (PList)malloc(sizeof(struct ListNode));
    TempA = headA;
    PList TempB = (PList)malloc(sizeof(struct ListNode));
    TempB = headB;
    while(TempA != NULL && TempB != NULL)
    {
        if(TempA == TempB)
          return TempA;
        TempA = TempA->next;
        TempB = TempB->next;
    }
    if(TempA == NULL)
    {
        TempA = headB;
         while(TempA != NULL && TempB != NULL)
         {
            if(TempA == TempB)
              return TempA;
            TempA = TempA->next;
            TempB = TempB->next;   
         }
         TempB = headA;
         while(TempA != NULL && TempB != NULL)
         {
            if(TempA == TempB)
              return TempA;
            TempA = TempA->next;
            TempB = TempB->next;   
         }
    }
    if(TempB == NULL)
    {
        TempB = headA;
        while(TempA != NULL && TempB != NULL)
         {
            if(TempA == TempB)
              return TempA;
            TempA = TempA->next;
            TempB = TempB->next;
        }
        TempA = headB;
        while(TempA != NULL && TempB != NULL)
         {
            if(TempA == TempB)
              return TempA;
            TempA = TempA->next;
            TempB = TempB->next;
        }
    }
    return NULL;

}

------------------------------------------------------------例题4----------------------------------------------------------

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.


Input:
[
  1->4->5,
  1->3->4,
  2->6
]
Output: 1->1->2->3->4->4->5->6


Solution 1:从上到下,让相邻的两个链表合并成新的有序链表接着向下合并。
struct ListNode *MergeSup(struct ListNode * A,struct ListNode * B)
{
struct ListNode * TempResult = (struct ListNode *)malloc(sizeof(struct ListNode));
    struct ListNode * Last = TempResult;
int count = 0;
    if(!A && B)
{
  while(B)
  {
  if(count == 0)
  {
  TempResult->val = B->val;
  TempResult->next = NULL;
  count++;
  }
  else
  {
      struct ListNode * T = (struct ListNode *)malloc(sizeof(struct ListNode));
  T->val = B->val;
  T->next = NULL;
  Last->next = T;
  Last = T;
  }
  B = B->next;
  }
  return TempResult;
}
    if(!B && A)
{
  while(A)
  {
  if(count == 0)
  {
  TempResult->val = A->val;
  TempResult->next = NULL;
  count++;
  }
  else
  {
  struct ListNode * T = (struct ListNode *)malloc(sizeof(struct ListNode));
  T->val = A->val;
  T->next = NULL;
  Last->next = T;
  Last = T;
  }
  A = A->next;
  }
  return TempResult;
}
if(!A && !B)
  return NULL;
    if(A->val < B->val)
    {
        TempResult->val = A->val;
        A = A->next;
    }
    else
    {
        TempResult->val = B->val;
        B = B->next;
    }   
    TempResult->next = NULL;
    while(A && B)
    {
        struct ListNode * TempNode = (struct ListNode *)malloc(sizeof(struct ListNode));
        if(A->val < B->val)
        {
            TempNode->val = A->val;
            A = A->next;
        }
        else
        {
            TempNode->val = B->val;
            B = B->next;
        } 
        TempNode->next = NULL;
        Last->next = TempNode;
        Last = TempNode;
    }
    while(A)
    {
        struct ListNode * TempNode = (struct ListNode *)malloc(sizeof(struct ListNode));
        TempNode->val = A->val;
        TempNode->next = NULL;
        Last->next = TempNode;
        Last = TempNode;
        A = A->next;
    }
    while(B)
    {
        struct ListNode * TempNode = (struct ListNode *)malloc(sizeof(struct ListNode));
        TempNode->val = B->val;
        TempNode->next = NULL;
        Last->next = TempNode;
        Last = TempNode;
        B = B->next;
    }
    return TempResult;
}


struct ListNode* mergeKLists(struct ListNode** lists, int listsSize) {
    if(listsSize == 0)
      return NULL;
    struct ListNode *Temp;
    struct ListNode *temp;
struct ListNode *Remember; 
    Temp = MergeSup(NULL,lists[0]);
    for(int i = 1;i < listsSize;i++)
    {
        Remember = Temp;
        Temp = MergeSup(Temp,lists[i]);
if(Remember)
{
temp = Remember->next;
while(temp)
{
free(Remember);
Remember = temp;
temp = Remember->next;
}
free(temp);
}
    }
    return Temp;
}
时间复杂度是O(m*n)






Solution 2:采用两两归并的思想来进行有序的组合,上面的由于组合的时候是线性的,也就是复杂度是N,现在采用两两归并则复杂度是logn,从本题的测试数据可以得出快大约80+倍方法二。




struct ListNode* mergeKLists(struct ListNode** lists, int listsSize) {
    if(listsSize == 0)
        return NULL;
    if(listsSize == 1)
        return lists[0];
    int Groups = listsSize;
    int count,i;
    while(Groups != 1)
    {
        count = 0;
        if(Groups % 2 == 0)
        {
            for(i = 0;i < Groups-1;i+=2)
                lists[count++] = MergeSup(lists[i],lists[i+1]);
            Groups = Groups/2;
        }
        else
        {
            for(i = 0;i < Groups-2;i+=2)
                lists[count++] = MergeSup(lists[i],lists[i+1]);
            lists[count++] = MergeSup(lists[i],NULL);
            //单出一组
            Groups = Groups/2+1;
        }         
    }
    return lists[0];
}


--------------------------------------------------------------------例题5--------------------------------

按照前序压缩,全部变成右子树,左子树全部为NULL;
Solution 1:
复刻数据到数组,重新创建树。
typedef struct TreeNode * TList;


void Pre_GetData(TList Root,int *Data,int *count)
{
    if(Root == NULL)
      return;
    Data[(*count)++] = Root->val;
    Pre_GetData(Root->left,Data,count);
    Pre_GetData(Root->right,Data,count);
}


void GetNodeNumbers(TList Root,int *count)
{
    if(Root == NULL)
      return;
    (*count)++;
    GetNodeNumbers(Root->left,count);
    GetNodeNumbers(Root->right,count);   
}


void flatten(struct TreeNode* root) {
    if(root == NULL)
       return NULL;
    int NodeNumbers = 0,count = 0;
    GetNodeNumbers(root,&NodeNumbers);
    int *Data = (int *)malloc(sizeof(int)*NodeNumbers);
    Pre_GetData(root,Data,&count);
    TList Last = (TList)malloc(sizeof(struct TreeNode));
    Last = root;
    Last->left = NULL;
    for(int i = 1;i < NodeNumbers;i++)
    {
        TList PNode = (TList)malloc(sizeof(struct TreeNode));
        PNode->val = Data[i];
        PNode->left = NULL;
        Last->right = PNode;
        Last = PNode;
    }
    Last->right = NULL;

}

-------------------------------------------例题6---------------------------------------------------

Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.
当K大于length的时候链表不动
Example:


Given this linked list: 1->2->3->4->5


For k = 2, you should return: 2->1->4->3->5


For k = 3, you should return: 3->2->1->4->5


Solution :利用栈来实现链表的反转
struct ListNode* reverseKGroup(struct ListNode* head, int k) {
    if(!head || !head->next)
        return head;
    int length = 0;
    struct ListNode *Go = head;
    while(Go)
    {
        length++;
        Go = Go->next;
    }
    if(k > length)
        return head;
    //数组模拟栈
    int count;
    struct ListNode** TempArray = (struct ListNode**)malloc(sizeof(struct ListNode*)*k);
    for(int j =0;j < k;j++)
        TempArray[j] = (struct ListNode *)malloc(sizeof(struct ListNode));
    struct ListNode* p = head;
    struct ListNode* TempHead = (struct ListNode *)malloc(sizeof(struct ListNode));
    TempHead->next = head;
    struct ListNode * Last;
    int first = 0;
bool flag = true;
    while(p)
    {
        for(count = 0;count < k;count++)
        {
            TempArray[count] = p;
            p = p->next;
            if(!p && count < k-1)
{
count++;
                flag = false;
                break;
}
        }
if(flag)
{
for(count = count-1;count >= 0;count--)
{
if(first == 0)
{
TempHead->next = TempArray[count];
Last = TempHead->next;
first++;
}
else
{
Last->next = TempArray[count];
Last = Last->next;
}
}
}
    }
//最后处理
if(count < k && count > 0)
{
    for(int i = 0;i < count;i++)
{
    Last->next = TempArray[i];
Last = Last->next;
}
}
    Last->next = NULL;
    return TempHead->next;

}



猜你喜欢

转载自blog.csdn.net/c_living/article/details/80978053