链表涉及的问题

 1.约瑟夫问题,循环链表解决

//https://blog.csdn.net/wenhai_zh/article/details/9620847
//循环链表解决
#include <stdio.h>
#include <stdlib.h>
#include<stdio.h> 
#include <stdlib.h>
 
typedef struct node//节点存放一个数据和指向下一个节点的指针
{
	int data;
	struct node* pnext;
} Node;
 
Node *link_create(int n)//创建n个节点的循环链表
{
	//先创建第1个节点
	Node *p,*q,*head;
	int i ;
	p = (Node *)malloc(sizeof(Node));
	head = p;
	p->data = 1;
 
	for(i = 2;i<=n;i++)//再创建剩余节点
	{
		q = (Node *)malloc(sizeof(Node));
		q->data = i;
		p->pnext = q;
		p = q;
	}
	p->pnext = head;//最后一个节点指向头部,形成循环链表
	return head;
}
 
void link_process(Node *head,int k,int m)//从编号为k(1<=k<=n)的人开始报数,数到m的那个人出列;
{
	int i;
	Node *p = head,*tmp1;
	while(p->data != k)//p指向的节点data为k
		p = p->pnext;
	
	while(p->pnext != p)
	{
		for(i=0;i<m-1;i++)//从下一个开始报数这里应该是m-1
		{
			tmp1 = p;
			p = p->pnext;
		}
		printf("%d ",p->data);
		tmp1->pnext= p->pnext;
		free(p);
		p = tmp1->pnext;
 
	}
	printf("%d ",p->data);
	free(p);
}
 
int main()
{
	
	Node *head = link_create(4);	
	link_process(head,1,3);
	system("pause");
	return 0;
}

Java解:

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入总人数:");
        int totalNum = scanner.nextInt();
        System.out.print("请输入报数的大小:");
        int cycleNum = scanner.nextInt();
        yuesefu(totalNum, cycleNum);
        scanner.close();
    }

    public static void yuesefu(int totalNum, int countNum) {
        // 初始化人数
        List<Integer> start = new ArrayList<Integer>();
        for (int i = 1; i <= totalNum; i++) {
            start.add(i);
        }
        // 从第K个开始计数
        int k = 0;
        while (start.size() > 0) {
            k = k + countNum;
            // 第m人的索引位置
            k = k % (start.size()) - 1;
            // 判断是否到队尾
            if (k < 0) {
                System.out.println(start.get(start.size() - 1));
                start.remove(start.size() - 1);
                k = 0;
            } else {
                System.out.println(start.get(k));
                start.remove(k);
            }
        }
    }
}

Python解法:

def josephus(n, k):
    if k == 1:
        print('survive:', n)
        return
    p = 0
    people = list(range(1, n + 1))
    while True:
        if len(people) == 1:
            break
        p = (p + (k - 1)) % len(people)
        print('kill:', people[p])
        del people[p]
    print('survive:', people[0])


if __name__ == '__main__':
    josephus(5, 2)

python中的del只是切断了引用,python的gc机制中对引用计数。

2.leetcode206 单链表反转问题

转载:https://blog.csdn.net/fx677588/article/details/72357389

	//翻转链表:迭代
	public static Node reverseList(Node head) {
		if(head == null || head.next == null) {
			return head;
		}
		Node p= head;
	    Node newH = null;
	    while(p!=null) {
	    	Node tmp = p.next;
	    	p.next = newH;
	    	newH = p;
	    	p = tmp;
	    }
		return newH;
		
	}
	//迭代方法翻转
	public static Node in_reverseList(Node head) {
		if(head == null || head.next == null)
			return head;
		Node newH = in_reverseList(head.next);
		head.next.next = head;
		head.next = null;
		return newH;
	}

3.快慢指针的应用问题

struct node{
    int val;
    struct node* next;
    node(int x) :val(x){}
};

node* reverseList(node* H)
{
	if(H == NULL || H->next == NULL){
		return H;
	}
	node* p = H, *newH = NULL;
	while(p != NULL){
		node* tmp = p->next;//不可以将p->next直接指向NewH,这样会导致下一个链表的地址被丢弃,无法访问,应该先设置一个临时值
		p->next = newH;//
		newH = p;//新链表头移动到p,扩张新链表
		p = tmp;//p指向下一个链表空间
	}
	return newH;
}
node* In_reverseList(node* H)
{
	if(H == NULL || H->next == NULL){
		return H;
	}
	node* newHead = In_reverseList(H->next);//一直循环到链表尾部
	H->next->next = H-;//翻转链表的指向
	H->next = NULL;//赋值NULL,防止链表错乱
	return newHead;//新链表永远只想原来链表的链表尾部
}
//判断是否有环
bool HasCircle(node *head)
{
	if(head == NULL)
		return false;
	node *slow = head, *fast = head;
	while(fast != NULL && fast->next != NULL){
		slow = slow->next;
		fast = fast->next->next;
		if(slow == fast){//相遇则存在环,快指针是慢指针两倍,相遇必然只绕了一圈
			return true;
		}
	}
	return false;
}
//存在环找到环的入口
node* judgeRing(node *head)
{
	node *slow = head;
	node * fast = head;
	
	while(fast && fast->next){
		slow = slow->next;
		fast = fast->next;
		if(slow == fast)break;//第一次相遇则结束,此时slow和fast为相遇点
	}
	
	if(fast == NULL || fast->next == NULL){
		return NULL;
	}
	slow = head;//slow调整指向head
	while(slow != fast){
		slow = slow->next;
		fast = fast->next;//fast指向相遇点,当fast到达相遇点,slow也到达相遇点,slow为入口;
	}
	return slow;
}

//找中间节点
node* FindMidNode(node *head)
{
	node *slow = head;
	node *fast = head;
	while(fast && fast->next){
		slow=slow->next;
		fast = fast->next->next;
	}
	return slow;
}
package datastructure;

public class LinkList {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Node head = new Node(0);
		Node current = head;
		Node temp = null;
		//构造循环链表
		for(int i=1;i<11;i++) {
			Node node = new Node(i);
			current.addNode(node);
			current = node;
			if(i ==3) {
				temp=node;
			}
		}
		current.next=temp;
		if(isCirlist(head)) {
			System.out.println("存在");
			System.out.println(findEn(head).data);
			
		}else {
			System.out.println("不存在");
		}
		
	}
	
	public static boolean isCirlist(Node head) {
		if(head==null) {
			return false;
		}
		Node slow = head;
		Node fast = head;
		int cir_len=1;
		while(fast != null && fast.next != null) {
			slow = slow.next;
			fast = fast.next.next;
			cir_len++;
			if(slow == fast) {
				System.out.println("环的长度是"+cir_len);//因为第一次相遇时的点距离入口的距离就是非环的长度,故记录下来正好是环长度
				return true;
			}
		}
		return false;
		
	}
	public static Node findEn(Node head) {
		Node slow = head;
		Node fast = head;
		while(fast!=null && fast.next!=null) {
			slow = slow.next;
			fast = fast.next.next;
			if(slow == fast) {
				break;//第一次相遇时停止
			}	
		}
		slow=head;
		int bin_len=0;//记录非环的长度
		while(slow != fast) {
			slow=slow.next;
			fast=fast.next;
			bin_len++;
		}
		System.out.println(bin_len);
		return slow;
		
	}
	

}

class Node{
	public int data;
	public Node next;
	
	public Node(int data) {
		this.data = data;
	}
	
	public void addNode(Node newNode) {
		if(this.next==null) {//这里的this应该是代表当前对象
			this.next=newNode;
		}else {
			this.next.addNode(newNode);
		}
	}
	public void ptintfNode() {
		System.out.print(this.data + "-->");
		if(this.next!=null) {
			this.next.ptintfNode();
		}
	}
}

关于this关键字的回顾:https://blog.csdn.net/u012176204/article/details/54580232

4.leetcode21 删除倒数第N个节点

	//删除倒数第N个节点,利用fast指针的方法,时间复杂度O(n)
	public static Node removeNthFromEnd(Node head,int n) {
		Node start = new Node(0);//建立一个空节点不装数据做哨兵避免链表为空或者需要移除表头
		start.next = head;
		Node slow = start;
		Node fast = start;
		
		for(int i=0;i<n+1;i++) {
			fast = fast.next;
		}
		while(fast != null) {
			slow = slow.next;
			fast = fast.next;
		}
		slow.next = slow.next.next;
		return start.next;
	}

5.leetcode 合并两个有序链表

	//合并两个有序链表
	public static Node mergeTwoList(Node list1,Node list2) {
		if(list1 == null)return list2;
		if(list2 == null)return list1;
		Node mergehead = null;
		if(list1.data < list2.data) {
			mergehead = list1;
			mergehead.next = mergeTwoList(list1.next,list2);
		}
		if(list1.data > list2.data) {
			mergehead = list2;
			mergehead.next = mergeTwoList(list1,list2.next);
		}
		return mergehead;
	}

 

    原文作者:约瑟夫环问题
    原文地址: https://blog.csdn.net/runkui8905/article/details/88598088
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞