Find Longest Unrepeated Letters in Cyclic Linked-List

无聊在版上闲逛发现类似 Cyclic Linked-List的题,自己想了一个试着写一下。

Find Longest Unrepeated Letters Length in Cyclic Linked-List (The List only Contain Upper letter from 'A' - 'Z')

For Example: ...A(head)-B-C-A-B-C-B-D-A(head)..... The Linked-List will start from A and traverse through B,C,A,B,C,B,D and Go back to A.

The Longest Unrepeated Letters Length is 4. (C-B-D-A)


我们可以把这道题分成几部分来进行解答:

1. 如何保存我们遍历到哪些结点的值

2. 如果是不带环的Linked-List,我们怎么找最长不重复子串

3. 如果Linked-List成环,我们需要注意哪些问题


对于第一问,因为题目里结点保存的值为'A' - 'Z', 所以我们可以用一个26位的boolean数组还保存某个值我们是否Visit过

先考虑不带环的Linked-List,我们怎么解决。比较直观的方法就是用两个Pointer,比如 i 和 j,分别指向当前子串的首和尾

1. 我们移动尾字符串,如果此结点的值是不重复的,更新boolean数组相对应位为True,并且将尾指针往后移动

2. 当尾指针遍历到一个值发现重复,首先,这是一个潜在的最大长度,而且说明,在之前我们肯定遍历过相同的值,那么这个值会落在从指针i 到指针 j 之间的位置 (第三点也会保证这一属性)

3. 此时,我们知道重复的字符在i 和 j 之间,那么我们不断移动指针i 去找到这一重复的字符。需要注意的是,在我们找到重复字符之前,首指针跳过的结点对应的字符,我们要给boolean[] 置False, 因为很简单,从i到j的子串中已经不包括i指针刚才跳过的字符了。

4. 当找到重复的字符后,两个指针同时向后移动1个位置,进行下一回的判断



看上面的3个图,当j指针移动到图2中B的位置的时候,首先从A-B-C是一个潜在的最大长度,其次,我们移动i指针去找之前重复的B,在找B的过程中,我们跳过了A,子串里面不包括A,所以我们要给boolean数组相对应的位置置False. 当我们发现重复的B之后,i 和 j各向后移动一位,继续这个过程。

好,现在我们知道了怎么在无环的Linked-List里面怎么找最大不重复子串,那么如果如图所示,闭环的Linked-List怎么办呢。

我们自然想到什么时候停的问题,如果不带环的Linked-List,只要尾指针移动的队尾就可以了,但是如果有环,如图所示,完全可能出现 C-B-D-A才是最大的不重复子串,换句话说,这回,我们需要首指针移动到队尾才能完成对所有可能的验证(因为最长子串的起始点可能在Linked-List里面任意一个节点)


OK,原理我们明白了,看一下实现这个功能的代码:

public int longestUnrepeat(){
		if (head==null) return 0;
		if (head.next==head) return 1;
		Node i = head;
		Node j = head;
		boolean imove = false;
		boolean[] visit = new boolean[26];
		int maxLen = 0;
		int Len = 0;
		while(true){
			if (i!=head) imove = true;
			if (i==head&&imove) break;
			if (!visit[j.val-'A']){
				visit[j.val-'A'] = true;
				j = j.next;
				Len++;
			}else{
				maxLen = Math.max(maxLen, Len);
				while(i.val!=j.val){
					visit[i.val-'A'] = false;
					i = i.next;
					Len--;
					if (i==head) return maxLen;
				}
				i = i.next;
				j = j.next;
			}
		}
		maxLen = Math.max(maxLen, Len);
		return maxLen;
	}

需要注意的几点:

1. 计算Len的时候,当尾指针j向前移动的时候,Len++,当首指针i向前移动的时候,Len--;

2. 当发现重复的时候,之前的字符子串是一个潜在的最大长度,我们要和之前maxLen进行比较,而当最后退出循环的时候,记得还要和maxLen比较一下当前的长度

3. 当Pointer i 循环完一圈,再次回到Head的时候,跳出循环,那么我们怎么判断它是第二次到达Head的呢? 我用了一个imove boolean变量默认False,当i从Head出发的时候,我们给它置True,说明它确实移动了,再次到达Head的时候便是第二次到达

4. node.val - 'A' 转化为数组index

5. 要小心没有结点,或者一个结点自成环的情况


完整直接能运行的版本请看下面:

public class LoopLinkedList {
	private Node head = null;
	private class Node{
		char val;
		Node next;
		public Node(char c){
			this.val = c;
		}
	}
	public void put(char c){
		if (head==null) head = new Node(c);
		else {
			Node x = head;
			while(x.next!=null) x = x.next;
			x.next = new Node(c);
		}
	}

	public void closeloop(){
		Node x  = head;
		while(x.next!=null)
			x = x.next;
		x.next = head;
	}
	
	public int longestUnrepeat(){
		if (head==null) return 0;
		if (head.next==head) return 1;
		Node i = head;
		Node j = head;
		boolean imove = false;
		boolean[] visit = new boolean[26];
		int maxLen = 0;
		int Len = 0;
		while(true){
			if (i!=head) imove = true;
			if (i==head&&imove) break;
			if (!visit[j.val-'A']){
				visit[j.val-'A'] = true;
				j = j.next;
				Len++;
			}else{
				maxLen = Math.max(maxLen, Len);
				while(i.val!=j.val){
					visit[i.val-'A'] = false;
					i = i.next;
					Len--;
					if (i==head) return maxLen;
				}
				i = i.next;
				j = j.next;
			}
		}
		maxLen = Math.max(maxLen, Len);
		return maxLen;
	}
	
	public static void main(String[] args){
		LoopLinkedList list1 = new LoopLinkedList();
		list1.put('A');
		list1.put('A');
		list1.put('A');
		list1.closeloop();
		int len = list1.longestUnrepeat();
		System.out.println("The Longest Unrepeated Length of Cyclic Linked-List -A-A-A- is ---->" + len);
		LoopLinkedList list2 = new LoopLinkedList();
		list2.put('A');
		list2.put('B');
		list2.put('C');
		list2.put('A');
		list2.put('B');
		list2.put('C');
		list2.put('B');
		list2.put('D');
		list2.closeloop();
		len = list2.longestUnrepeat();
		System.out.println("The Longest Unrepeated Length of Cyclic Linked-List -A-B-C-A-B-C-B-D- is ---->" + len);
	}
}


最后的输出为:

The Longest Unrepeated Length of Cyclic Linked-List -A-A-A- is ---->1

The Longest Unrepeated Length of Cyclic Linked-List -A-B-C-A-B-C-B-D- is ---->4


只测试了几个例子,不知道还有没有别的情况没有考虑充分,欢迎来捉虫 ^_^

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
As an AI language model, I cannot provide you with the exact solution you need without further details. However, here is a general approach to find the longest distance in a binary tree using Python: 1. Define a class for a binary tree node with attributes for the node value, left child, and right child. 2. Define a function that recursively traverses the binary tree and returns the height of the tree starting from a given node. 3. Define a function that recursively traverses the binary tree and returns the longest distance between two nodes in the tree. 4. In the function defined in step 3, for each node, calculate the longest distance that passes through that node and update the maximum distance seen so far. 5. Call the function defined in step 3 starting from the root node of the binary tree. Here is a sample implementation of the above approach: ``` class Node: def __init__(self, value): self.value = value self.left = None self.right = None def height(root): if root is None: return 0 return 1 + max(height(root.left), height(root.right)) def longest_distance(root): if root is None: return 0 left_height = height(root.left) right_height = height(root.right) left_distance = longest_distance(root.left) right_distance = longest_distance(root.right) return max(left_height + right_height, max(left_distance, right_distance)) root = Node(1) root.left = Node(2) root.right = Node(3) root.left.left = Node(4) root.left.right = Node(5) root.right.left = Node(6) root.right.right = Node(7) print(longest_distance(root)) ``` This code will output the longest distance between any two nodes in the binary tree.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值