`
lgsun592
  • 浏览: 54643 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

某互联网公司面试题(二)

    博客分类:
  • Java
阅读更多

接上贴http://lgsun592.iteye.com/admin/blogs/1066179 ,这也是其中的一道面试题

问题:一个链表可能包含环,如何检测并确定环的位置,如图:



 


方法有2:

1.记录法,通过某种方式把访问过的记录记录下来,然后访问下一个节点的时候查询下访问记录(我当时只想到了此方法,唉);

如果是外部标记的话,需要遍历1+2+...+(P+L-1)+P+(P+L)个节点,约O((max(P,L))^2),程序实现的就是此种方法

如果是内部标记的话,只需要遍历P+L个节点,速度最快的了


2.追赶法,类似在操场跑圈,两人同时起步,快的人和慢的人第一次相遇的时候,快的肯定比慢的多跑一圈,以此进行推算

第一次跑:两人同时从起点出发,第一个人P1速度为1,第二个人P2速度为2,相遇的时候P1跑的路程N=P+C,P2的路程=2N,可以推出此园的周长KL=P+C=N(K=1,2...)

第二次跑:P1的接上次位置,速度为1,P2从起点出发,速度为1,这次经过距离P后2人相遇,即在圆的起点相遇
推理:
KL = P + C
=>
KL - C = P
 


第二次相遇后,可以获得P的值,那么就可以确定此环形的起止位置了(程序实现的是K=1的情况)

废话不多说了,看代码吧

/**  
 * Class @CircleLinklist.java
 * 环形链表检测
 * @author  lgsun
 * Date: 2011-6-2
 */

package org.lgsun.linklist;

import java.text.MessageFormat;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

@SuppressWarnings("all")
public class CircleLinklist<E>
{
	private static final int LENGTH = 16;
	private Entry<E> header;

	public static void main(String[] args)
	{
		CircleLinklist<String> circle = new CircleLinklist<String>();
		circle.createLinkList();
		circle.print();
		circle.method1();
		circle.method2();
	}

	/**
	 * 方法1
	 * 1.遍历链表 
	 * 2.将访问过的节点的hashcode值保存起来 
	 * 3.如果某节点的hashcode值已经存在,那么存在环
	 */
	public void method1()
	{
		int start = -1;
		int curNum = 0;
		Entry<E> curEntry = header;
		List<Integer> codeList = new LinkedList<Integer>();

		//遍历链表 
		while (curEntry.next != null)
		{
			if (codeList.size() == 0)
			{
				codeList.add(curEntry.hashCode());
			}
			else
			{
				//如果存在,则包含环
				if (codeList.contains(curEntry.hashCode()))
				{
					start = codeList.indexOf(curEntry.hashCode());
					break;
				}
			}

			codeList.add(curEntry.hashCode());
			curEntry = curEntry.next;
			curNum++;
		}

		if (start != -1)
		{
			System.out.println(MessageFormat.format(
					"方法1:此链表中包含环,从第{0}个节点到第{1}个节点。", start, curNum));
		}
		else
		{
			System.out.println("方法1:此链表中不包含环!");
		}
	}

	/**
	 * 方法2
	 * 追赶法,数学啊,数学
	 */
	public void method2()
	{
		int start = 0;
		int length = 0;
		boolean isCircle = false;
		Entry<E> firstEntry = header;
		Entry<E> secondEntry = header;

		//第一次,p1 速度为1,p2速度为2
		while (secondEntry != null)
		{
			length++;
			if (length > 1)
			{
				// 直接比较内存地址
				if (firstEntry == secondEntry)
				{
					isCircle = true;
					break;
				}
			}

			if (firstEntry.next != null)
			{
				firstEntry = firstEntry.next;
			}
			else
			{
				break;
			}

			if (secondEntry.next != null)
			{
				secondEntry = secondEntry.next.next;
			}
			else
			{
				break;
			}
		}

		if (isCircle)
		{
			secondEntry = header;

			//第二次,p1速度为1,p2速度为1
			for (int i = 0; i < length; i++)
			{
				start++;
				// 直接比较内存地址
				if (firstEntry == secondEntry)
				{
					// 从头到尾,交点总共算了3次,所以减2
					length = length + start - 2;
					break;
				}

				if (firstEntry.next != null)
				{
					firstEntry = firstEntry.next;
				}
				else
				{
					break;
				}

				if (secondEntry.next != null)
				{
					secondEntry = secondEntry.next;
				}
				else
				{
					break;
				}
			}
		}
		else
		{
			System.out.println("方法2:此链表中不包含环!");
		}

		System.out.println(MessageFormat.format(
				"方法2:此链表中包含环,从第{0}个节点到第{1}个节点。", start, length));
	}

	/**
	 * 向链表中增加节点
	 */
	public void add(Entry<E> entry)
	{
		if (header == null)
		{
			header = entry;
		}
		else
		{
			entry.next = header;
			header = entry;
		}
	}

	/**
	 * 创建一个带环的链表
	 */
	public void createLinkList()
	{
		String disturb = "disturb";

		Entry footer = null;
		Entry node = new Entry<String>("node");

		Random random = new Random();

		for (int i = 0; i < LENGTH; i++)
		{
			// 在长度1/2处加入指定节点
			if (i == (LENGTH / 2))
			{
				add(node);
			}
			else if (i == (LENGTH / 4) || i == (LENGTH * 3 / 4))
			{
				// 加入干扰节点
				add(new Entry(disturb));
			}
			else
			{
				// 加入随机节点
				String e = String.valueOf(random.nextInt(9999));
				add(new Entry(e));
			}

			// 获取尾节点
			if (i == 0)
			{
				footer = header;
			}
		}

		// 给尾节点赋值为确定节点,产生环
		footer.next = node;
	}

	/**
	 * 输出此链表
	 */
	public void print()
	{
		Entry<E> flag = header;

		System.out.print("header:");
		for (int i = 1; i < LENGTH + 4; i++)
		{
			if (i != 0)
			{
				System.out.print("=>");
			}
			System.out.print("["+i+"]"+flag.element.toString());
			flag = flag.next;
		}
		System.out.println();
		flag = header;
	}
}

class Entry<E>
{
	E element;
	Entry<E> next;

	Entry(E element)
	{
		this.element = element;
		this.next = null;
	}
}
 


       不知道发此帖是对是错,发完上一帖已经有朋友M我说,他面试的时候也碰到的同样的题了,可见此公司的题库更新很慢吗 ,希望大家早日找到自己喜欢的工作哦。

       我是在洗澡的时候完成的此题的编码构思,所以一不小心和地板来了个亲密接触


参考资料:http://blogold.chinaunix.net/u1/41845/showart_2019391.html

 

  • 大小: 30.9 KB
分享到:
评论
17 楼 sebatinsky 2011-06-08  
菜鸟从中飞过,,,。心慌慌。
16 楼 marshaldong 2011-06-08  
两层循环,如果内层循环的节点有等于外层循环的节点的,说明有环,后续分享代码:

public class TestCircularList {
	static class Node<T> {
		T value;
		Node<T> next;

		Node(Node<T> next, T value) {
			this.value = value;
			this.next = next;
		}

	}

	public static Node<Integer> generateLinkList(int number) {
		Node<Integer> t = new Node<Integer>(null, 0);
		Node<Integer> temp = t;
		Node<Integer> temp1 = null;
		for (int i = 1; i < number; i++) {
			temp1 = new Node<Integer>(null, i % number);
			temp.next = temp1;
			temp = temp1;
		}
		temp.next = t.next.next.next;// construct circular linked list
		return t;
	}

	public static void main(String[] args) {
		Node<Integer> node = TestCircularList.generateLinkList(10);
		TestCircularList.traverse(node, 10);
	}

	/**
	 * 
	 * @param <T>
	 * @param node
	 *            the head node
	 * @param length
	 *            the actural number of nodes of the linked list
	 */
	public static <T> void traverse(Node<T> node, int length) {
		Node<T> temp = node;
		Node<T> temp1 = null;
		while (temp != null) {
			temp1 = temp.next;
			int tailIndex = --length;
			while (temp1 != null && tailIndex != 0) {
				if (temp1 == temp) {
					System.out.println("has rings!");
					System.out.println("Begin node value: " + temp.value);
					while (temp.next != temp1) {
						System.out.println(temp.next.value);
						temp = temp.next;
					}
					System.out.println("End node value: " + temp.value);
					return;
				}
				temp1 = temp1.next;
				tailIndex--;
			}
			temp = temp.next;
		}
	}
}

似乎和找出一个List里两个值相同的元素的索引是一个解法,只不过这里是比较两个节点的相等(内存地址相同),再思考。
15 楼 enefry 2011-06-07  
支持hashMap说法.遍历是必须的.只是需要多余空间的支持.
14 楼 fivestarwy 2011-06-07  
Durian 写道
这样的题没啥意义。
除非你喜欢信息奥林匹克竞赛题。

普通的数据结构习题,信息奥林匹克不知道比这难多少倍

13 楼 antonia 2011-06-07  
这些题目看着好难。。。。
12 楼 lance4t 2011-06-07  
别去百度浪费大好青春。。。
11 楼 java_web 2011-06-07  

完全看不懂啊
学习学习啊
10 楼 wuzaizhong283 2011-06-07  
这是百度的题
9 楼 dwbin 2011-06-07  
我觉着还是别去吧,这样的所谓的算法题没市场的。
8 楼 Durian 2011-06-06  
cttnbcj 写道
Durian 写道
这样的题没啥意义。
除非你喜欢信息奥林匹克竞赛题。

  有些东西做不出来就进不去,那就搞不定了。。。。。

想进入好的公司真的需要做足功课。不过对于这些算法题,我不行,也不打算浪费青春去学。
7 楼 thihy 2011-06-06  
avi2 写道
这是什么问题?,他们想要什么样的人?


HULU
6 楼 avi2 2011-06-06  
这是什么问题?,他们想要什么样的人?
5 楼 cttnbcj 2011-06-06  
Durian 写道
这样的题没啥意义。
除非你喜欢信息奥林匹克竞赛题。

  有些东西做不出来就进不去,那就搞不定了。。。。。
4 楼 Durian 2011-06-06  
这样的题没啥意义。
除非你喜欢信息奥林匹克竞赛题。
3 楼 wyp12 2011-06-06  
遍历一次链表,没次遍历一个节点,对该节点取hash,然后保存在一个hashmap中,key为hash值,value为该节点的位置,可以用一个自增i变量表示,每次访问一个节点的时候,查询下hashmap中是否已存在该节点,存在,则说明出现了一个环
2 楼 小怪兽 2011-06-06  
在校学生...表示压力巨大
1 楼 asst2003 2011-06-05  
应该使用HashSet:遍历链表,在访问一个节点后,把这个节点放入HashSet中;在访问一个节点前先调用HashSet
的contains(Object node)方法来判断该节点是否已访问过,如果是,这个节点就是环的位置。


你的method1()使用了LinkedList的contains(Object node)方法。该方法会从头开始依次遍历链表来查找是否包含指定的节点,效率比较低。HashSet底层是通过包装了一个HashMap来实现的,它的contains(node)方法其实是调用HashMap的containsKey(Object node)来实现的,由于散列的缘故,这个查找的执行效率会很高。

相关推荐

    出租车计费功能(java版解决方法)某大型互联网公司面试题,还附送测试代码哦

    出租车起步价14元,含3公里 起步价之后,每公里2.5元 晚上11点之后(含),次日6点前(不含)起步价18元,含3公里。计价以上车时间为准,不考虑乘坐期间从白天到晚上的情况。 晚上起步价之后,每公里3元 ...

    2019年一线互联网公司Java高级面试题总结

    根据给定文件的信息,我们可以将知识...以上知识点涵盖了Java高级面试题的多个方面,包括基本概念、设计模式、框架应用以及分布式系统的设计与实现。对于准备面试的开发者来说,深入理解并掌握这些知识点是非常重要的。

    IOS面试题--(某大型移动互联网公司)

    这些题目涵盖了iOS开发中的多个核心知识点,包括动态语言特性、内存管理、Objective-C语法、多线程、协议、文件...以上就是这些面试题所涵盖的iOS开发核心知识的详细解释,对于准备面试或巩固iOS开发基础非常有帮助。

    某互联网大厂MySQL面试题-20题(附带答案)

    MySQL是广泛应用于...这些面试题涵盖了MySQL基础知识的核心部分,对于准备面试或者想要深入理解MySQL的开发者来说非常有价值。通过掌握这些知识点,可以有效地应对MySQL相关的技术面试,提升在互联网大厂的竞争力。

    某互联网大厂Java面试题-18题(附带答案)

    Java 是一种广泛应用于互联网行业的编程语言,特别是在大型企业中,Java 的基础知识是面试者必须掌握的关键技能。以下是一些从上述题目中提炼出的重要知识点: 1. **Java 内存模型**:Java 内存模型(JMM)规定了...

    sql模拟面试题.

    以下是对给定面试题的详细解析和扩展: 1. 查询“001”课程比“002”课程成绩高的所有学生的学号: 这个问题是通过子查询来解决的,首先分别从SC表中获取"001"课程和"002"课程的学生分数,然后通过内连接(INNER ...

    1000道 互联网Java工程师面试题 485页_PDF密码解除.pdf

    #### MyBatis面试题详解 **1. 什么是MyBatis?** MyBatis是一个优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射。MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。MyBatis可以通过简单的...

    机器学习面试题(3).docx

    "机器学习面试题(3)" 决策树分类 决策树分类是机器学习中的一种重要算法,用于解决分类问题。决策树分类的基本思想是通过递归地将特征空间分割成更小的子空间,直到每个子空间只包含同一类别的样本为止。决策树...

    各大公司面试题-曾锤鑫面试题.txt

    在IT行业中,这个问题通常会被用来了解应聘者的学术背景或其在某一技术领域的专长。例如,应聘者可能会提到他们具有计算机科学、软件工程等学位,或者是精通Java、Python等编程语言。 ### 2. XX项目需要什么,用...

    互联网大厂Mysql面试题精选55题

    面试中可能会针对以上某一点深入讨论,也可能综合多个知识点进行实际问题的解决。因此,全面理解和实践这些MySQL核心概念对于成功通过互联网大厂的面试至关重要。在复习过程中,结合实际案例和实践经验将更有利于...

    UI设计师面试题

    UI 设计师面试题知识点总结 本资源摘要信息涵盖了 UI 设计师面试题的知识点,涵盖了 UI 设计师面试题的知识点,涉及到 UI 设计的方方面面,包括界面设计、视觉设计、交互设计、用户体验、产品设计、网页设计、APP ...

    2020年最新5G基础考试题及答案-榆林市某讯公司面试试题.docx

    【5G基础知识】 5G(第五代移动通信技术)是当前通信行业的热点...以上就是5G基础考试题涉及的主要知识点,涵盖了5G网络架构、信道配置、物联网技术、资源管理等多个方面。掌握这些知识对于理解5G网络的运作至关重要。

    2020年最新5G基础考试题及答案-榆林市某讯公司面试试题.pdf

    。。。

    算法面试题总结.docx

    ### 算法面试题总结 #### 一、两数之和 **题目描述:** 给定一个整数数组 `nums` 和一个目标值 `target`,请在该数组中找出和为 `target` 的那两个整数,并返回它们的数组下标。 **示例:** 假设给定数组 `nums...

    本人收藏多年的常见Java面试题 非常有用!(附答案)

    程序员在面试 Java 开发岗位时经常会遇上各类笔试面试题,针对这些笔试面试题做准备是必要的环节,在此过程中也能加深对 Java 知识的理解。 本面试试题均来自于网上。按照 Java 知识点的分类整理出试题,每道题都有...

    IT软件面试题及应聘要求

    二、谷歌面试题与应聘要求 谷歌以其独特的面试流程闻名,注重面试者的综合能力: 1. 技术实力:除了基本的编程和算法能力,谷歌还会测试你在特定领域的深度,如机器学习、大数据处理等。 2. 软技能:沟通能力、团队...

    linux面试题 企业面试题

    ### Linux面试题解析 #### 一、Linux基本概念与文件系统 **1. 在Linux系统中,以文件方式访问设备。** - **知识点解析:**Linux操作系统中的一个重要特性就是几乎所有的设备都被视为文件来处理。这包括硬件设备如...

    2020年最新5G基础考试题及答案-湘潭市某讯公司二面试题.pdf

    。。。

    2020年最新5G基础考试题及答案-湘潭市某讯公司二面试题.docx

    。。。

Global site tag (gtag.js) - Google Analytics