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;
}