简体   繁体   English

java中的单链表

[英]Singly linked list in java

i just found this difficult interview question online and I was hoping someone could help me make sense of it. 我刚刚在网上找到了这个困难的面试问题,我希望有人可以帮助我理解它。 It is a generic question...given a singly linked list, swap each element of the list in pairs so that 1->2->3->4 would become 2->1->4->3. 这是一个通用的问题......给定一个单链表,将列表中的每个元素成对交换,使1-> 2-> 3-> 4成为2-> 1-> 4-> 3。

You have to swap the elements, not the values. 您必须交换元素,而不是值。 The answer should work for circular lists where the tail is pointing back to the head of the list. 答案应该适用于循环列表,其中尾部指向列表的头部。 You do not have to check if the tail points to an intermediate (non-head) element. 您不必检查尾部是否指向中间(非头部)元素。

So, I thought: 所以我认为:

public class Node
{
     public int n;     // value
     public Node next; // pointer to next node
}

What is the best way to implement this? 实现这个的最佳方法是什么? Can anyone help? 有人可以帮忙吗?

Simple recursive solution in Java: Java中的简单递归解决方案:

public static void main(String[] args)
{
    Node n = new Node(1);
    n.next = new Node(2);
    n.next.next = new Node(3);
    n.next.next.next = new Node(4);
    n.next.next.next.next = new Node(5);

    n = swap(n);
}
public static Node swap(Node n)
{
    if(n == null || n.next == null)
        return n;
    Node buffer = n;
    n = n.next;
    buffer.next = n.next;
    n.next = buffer;
    n.next.next = swap(buffer.next);
    return n;
 }

public static class Node
{
    public int data; // value
    public Node next; // pointer to next node

    public Node(int value)
    {
        data = value;
    }
}

I agree with @Stephen about not giving the answer (entirely), but I think I should give you hints. 我同意@Stephen没有给出答案(完全),但我想我应该给你提示。

An important thing to understand is that Java does not explicitly specify pointers - rather, whenever a non-primitive (eg not char , byte , int , double , float , long , boolean , short ) is passed to a function, it is passed as a reference. 要理解的一件重要事情是Java没有显式指定指针 - 相反,只要非基元(例如,不是charbyteintdoublefloatlongbooleanshort )传递给函数,它就会被传递为一个参考。 So, you can use temporary variables to swap the values. 因此,您可以使用临时变量来交换值。 Try to code one yourself or look below: 尝试自己编写代码或查看以下内容:

 public static void swapNodeNexts(final Node n1, final Node n2) {  
    final Node n1Next = n1.next;  
    final Node n2Next = n2.next;  
    n2.next = n1Next;  
    n1.next = n2Next;  
 }  

Then you'll need a data structure to hold the Node s. 然后,您将需要一个数据结构来保存Node It's important that there be an even number of Node s only (odd numbers unnecessarily complicate things). 重要的是只有偶数个Node (奇数不必要地使事情变得复杂)。 It's also necessary to initialize the nodes. 还需要初始化节点。 You should put this in your main method. 你应该把它放在你的main方法中。

  public static final int NUMPAIRS = 3;
 public static void main(final String[] args) {
    final Node[] nodeList = new Node[NUMPAIRS * 2];
    for (int i = 0; i < nodeList.length; i++) {
        nodeList[i] = new Node();
        nodeList[i].n = (i + 1) * 10;
        // 10 20 30 40
    }
    // ...
 } 

The important part is to set the Node next values. 重要的是设置Node下一个值。 You can't just loop through with a for loop for all of them, because then the last one's next would throw an IndexOutOfBoundsException . 你不能只是通过一个循环for回路所有的人,因为这样最后一个人的next会抛出IndexOutOfBoundsException Try to make one yourself, or peek at mine. 试着自己制作一个,或偷看我的。

  for (int i = 0; i < nodeList.length - 1; i++) {
    nodeList[i].next = nodeList[i + 1];
 }
 nodeList[nodeList.length - 1].next = nodeList[0];

Then run your swap function on them with a for loop. 然后使用for循环在它们上运行swap函数。 But remember, you don't want to run it on every node… think about it a bit. 但请记住,你不想在每个节点上运行它......想一想。

If you can't figure it out, here is my final code: 如果你无法弄清楚,这是我的最终代码:

 // Node
 class Node {
    public int n; // value
    public Node next; // pointer to next node

    @Override
    public String toString() {
        return "Node [n=" + n + ", nextValue=" + next.n + "]";
    }

 }

 // NodeMain
 public class NodeMain {
    public static final int NUMPAIRS = 3;

    public static void main(final String[] args) {
        final Node[] nodeList = new Node[NUMPAIRS * 2];
        for (int i = 0; i < nodeList.length; i++) {
            nodeList[i] = new Node();
            nodeList[i].n = (i + 1) * 10;
            // 10 20 30 40
        }
        for (int i = 0; i < nodeList.length - 1; i++) {
            nodeList[i].next = nodeList[i + 1];
        }
        nodeList[nodeList.length - 1].next = nodeList[0];

        // This makes 1 -> 2 -> 3 -> 4 -> 1 etc.
        printNodes(nodeList);

        for (int i = 0; i < nodeList.length; i += 2) {
            swapNodeNexts(nodeList[i], nodeList[i + 1]);
        }

        // Now: 2 -> 1 -> 4 -> 3 -> 1 etc.
        printNodes(nodeList);

    }

    private static void printNodes(final Node[] nodeList) {
        for (int i = 0; i < nodeList.length; i++) {
            System.out.println("Node " + (i + 1) + ": " + nodeList[i].n
                    + "; next: " + nodeList[i].next.n);
        }
        System.out.println();
    }

    private static void swapNodeNexts(final Node n1, final Node n2) {
        final Node n1Next = n1.next;
        final Node n2Next = n2.next;
        n2.next = n1Next;
        n1.next = n2Next;
    }
 } 

I hope you were able to figure out at least some of this with guidance. 我希望你能够在指导下弄清楚其中的一部分。 More importantly, however, it's important that you understand the concepts here. 但更重要的是,了解这里的概念非常重要。 If you have any questions, just leave a comment. 如果您有任何疑问,请发表评论。

Methods needed to run this program : 运行此程序所需的方法:

public static void main(String[] args) {
    int iNoNodes = 10;
    System.out.println("Total number of nodes : " + iNoNodes);
    Node headNode = NodeUtils.createLinkedListOfNElements(iNoNodes);
    Node ptrToSecondNode = headNode.getNext();
    NodeUtils.printLinkedList(headNode);
    reversePairInLinkedList(headNode);
    NodeUtils.printLinkedList(ptrToSecondNode);
}

Approach is almost same, others are trying to explain. 方法几乎相同,其他人正试图解释。 Code is self-explainatory. 代码是自我解释的。

private static void reversePairInLinkedList(Node headNode) {
    Node tempNode = headNode;
    if (tempNode == null || tempNode.getNext() == null)
        return;
    Node a = tempNode;
    Node b = tempNode.getNext();
    Node bNext = b.getNext(); //3
    b.setNext(a);
    if (bNext != null && bNext.getNext() != null)
        a.setNext(bNext.getNext());
    else
        a.setNext(null);
    reversePairInLinkedList(bNext);
}

Algo(node n1) - Algo(节点n1) -

keep 2 pointers n1 and n2, at the current 2 nodes. 在当前的2个节点保留2个指针n1和n2。 n1 --> n2 --->... n1 - > n2 ---> ......

  • if(n1 and n2 link to each other) return n2; if(n1和n2相互链接)返回n2;

  • if(n1 is NULL) return NULL; if(n1为NULL)返回NULL;

  • if(n2 is NULL) return n1; if(n2为NULL)返回n1;

  • if(n1 and n2 do not link to each other and are not null) if(n1和n2不相互链接且不为空)

  • change the pointer of n2 to n1. 将n2的指针更改为n1。

  • call the algorthm recursively on n2.next 在n2.next上递归调用algorthm

  • return n2; 返回n2;

Code (working) in c++ 用c ++编写代码(工作)

#include <iostream>
using namespace std;

class node
{
public:
int value;
node* next;
node(int val);
};

node::node(int val)
{
value = val;
}

node* reverse(node* n)
{

if(n==NULL) return NULL;
node* nxt = (*n).next;
if(nxt==NULL) return n;

if((*nxt).next==n) return nxt;
else
    {
node* temp = (*nxt).next;
(*nxt).next = n;
 (*n).next   = reverse(temp);
}
return nxt;

}
void print(node* n)
{
node* temp = n;
while(temp!=NULL)
    {
    cout<<(*temp).value;
    temp = (*temp).next;
    }
cout << endl;

}

int main()
{
node* n = new node(0);
node* temp = n;

for(int i=1;i<10;i++)
{

node* n1 = new node(i);
(*temp).next = n1;
temp = n1;
}
print(n);
node* x = reverse(n);
print(x);

} }

//2.1 , 2.2 Crack the code interview

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>

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




 struct Node *insert(struct Node *head,int data){
    struct Node *temp,*ptr;

     temp = (struct Node*)malloc(sizeof(struct Node));
     temp->info=data;
     temp->next=NULL;

     if(head==NULL)
        head=temp;

     else{
        ptr=head;
        while(ptr->next!=NULL)
        {
        ptr=ptr->next;
        }
        ptr->next=temp;
     }
    return head;
 }


 struct Node* reverse(struct Node* head){
    struct Node *current,*prev,*next;
    current = head;
    prev=NULL;
    while(current!=NULL){
        next=current->next;
        current->next = prev;
        prev=current;
        current=next;
    }
    head=prev;
    return head;
}
/*nth till last element in linked list*/

void nthlastElement(struct Node *head,int n){
    struct Node *ptr;
    int last=0,i;
    ptr=head;

    while(ptr!=NULL){
        last++;
        //printf("%d\n",last);
        ptr=ptr->next;
    }

    ptr=head;
    for(i=0;i<n-1;i++){
        ptr=ptr->next;      
    }

    for(i=0;i<=(last-n);i++){
        printf("%d\n",ptr->info);
        ptr=ptr->next;
    }
}

 void display(struct Node* head){
      while(head!=NULL){
        printf("Data:%d\n",head->info);
        head=head->next;
      }
 }



 void deleteDup(struct Node* head){
    struct Node *ptr1,*ptr2,*temp;

    ptr1=head;

    while(ptr1!=NULL&&ptr1->next!=NULL){
            ptr2=ptr1;
          while(ptr2->next!=NULL){
            if(ptr1->info==ptr2->next->info){
                temp=ptr2->next;
                ptr2->next=ptr2->next->next;
                free(temp);
            }
            else{
              ptr2=ptr2->next;
              }

          }  
          ptr1=ptr1->next;
    }
}

 void main(){
    struct Node *head=NULL;
    head=insert(head,10);
    head=insert(head,20);
    head=insert(head,30);
    head=insert(head,10);
    head=insert(head,10);
    printf("BEFORE REVERSE\n"); 
    display(head);
    head=reverse(head);
    printf("AFTER REVERSE\n");
    display(head);
    printf("NTH TO LAST\n");
    nthlastElement(head,2);
     //printf("AFTER DUPLICATE REMOVE\n");
    //deleteDup(head);
    //removeDuplicates(head);
     //display(head);
 }

The general approach to take is to step through the list, and on every other step you reorder the list nodes by assigning the node values. 采用的一般方法是逐步执行列表,并在每个其他步骤中通过分配node值对列表节点重新排序。

But I think you will get more out of this (ie learn more) if you actually design, implement and test this yourself. 但是,如果您自己设计,实施和测试,我认为您将从中获得更多(即了解更多)。 (You don't get a free "phone a friend" or "ask SO" at a job interview ...) (你在面试时没有得到免费的“打电话给朋友”或“问SO”)

Yep, write an iterative routine that progresses two links in each iteration. 是的,编写一个迭代例程,在每次迭代中前进两个链接。 Remember the link from the previous iteration so that you can back-patch it, then swap the current two links. 记住上一次迭代的链接,以便您可以对其进行补丁,然后交换当前的两个链接。 The tricky parts are getting started (to a small extent) and knowing when to finish (to a larger one), especially if you end up having an odd number of elements. 棘手的部分是开始(在很小程度上)并知道何时完成(更大的),特别是如果你最终有一个奇数个元素。

public static Node swapInPairs(Node n)
{
    Node two;
    if(n ==null ||n.next.next ==null)
    {
        Node one =n;
        Node twoo = n.next;
        twoo.next = one;
        one.next =null;
        return twoo;            
    }
    else{
        Node one = n;
        two = n.next;   
        Node three = two.next;
        two.next =one;
        Node res = swapInPairs(three);
        one.next =res;          
    }
    return two;
}

I wrote the code at atomic level. 我在原子级写了代码。 So i hope it is self explanatory. 所以我希望它是自我解释的。 I tested it. 我测试了它。 :) :)

public static Node swapPairs(Node start)
{
    // empty or one-node lists don't need swapping
    if (start == null || start.next == start) return start;

    // any list we return from here on will start at what's the second node atm
    Node result = start.next;

    Node current = start; 
    Node previous = null;     // so we can fix links from the previous pair

    do
    {
        Node node1 = current;
        Node node2 = current.next;

        // swap node1 and node2 (1->2->? ==> 2->1->?)
        node1.next = node2.next;
        node2.next = node1;

        // If prev exists, it currently points at node1, not node2.  Fix that
        if (previous != null) previous.next = node2;

        previous = current;

        // only have to bump once more to get to the next pair;
        // swapping already bumped us forward once
        current = current.next;

    } while (current != start && current.next != start);

    // The tail needs to point at the new head
    // (if current == start, then previous is the tail, otherwise current is)
    ((current == start) ? previous : current).next = result;

    return result;
}
public class Node
{
     public int n;     // value
     public Node next; // pointer to next node
}

Node[] n = new Node[length];

for (int i=0; i<n.length; i++)
{
    Node tmp = n[i];
    n[i] = n[i+1];
    n[i+1] = tmp;
    n[i+1].next = n[i].next; 
    n[i].next = tmp;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM