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

Google面试题解说性能之一:字符串运算VS数字运算

    博客分类:
  • Java
阅读更多

看到JavaEye上的几个人在讨论算法问题,其中一个就是Google的一个面试题,我也试了一下,而且可能比一般人试得程度更深一些,借这个题目简单的说说几个性能问题。这个是第一个,后面还会继续几个其它的讨论。讨论只是提点一下,主要还是要你自己读源代码并比较不同的实现为什么会有这么大的差别。
注意,程序的运行结果是在JDK1.4.2上的,其它版本的JDK的运行结果可能稍有不同。

先看代码:
public class GoogleFn {
    private static int MAX = 13200000;

    private static int count1(int number) {
        int result = 0;
        String target = number + "";
        int index = target.indexOf("1");
        while (index >= 0) {
            result++;
            index = target.indexOf("1", index + 1);
        }
        return result;
    }

    private static int count2(int n) {
        int count = 0;
        while (n > 0) {
            int mod = n % 10;
            if (mod == 1)
                count++;
            n = n / 10;
        }
        return count;
    }
    private static void method1() {
        long start = System.currentTimeMillis();
        int result = 0;
        for (int i = 1; i < MAX; i++) {
            result += count1(i);
            if (result == i) {
                System.out.println("Find " + i + ", " + (System.currentTimeMillis() - start) + "ms");
            }
        }
    }

    private static void method2() {
        long start = System.currentTimeMillis();
        int result = 0;
        for (int i = 1; i < MAX; i++) {
            result += count2(i);
            if (result == i) {
                System.out.println("Find " + i + ", " + (System.currentTimeMillis() - start) + "ms");
            }
        }
    }

    public static void main(String[] args) {
        method1();
        method2();
    }
}
运行结果是:
Find 1, 16ms
Find 199981, 219ms
Find 199982, 219ms
Find 199983, 219ms
Find 199984, 219ms
Find 199985, 219ms
Find 199986, 219ms
Find 199987, 219ms
Find 199988, 219ms
Find 199989, 219ms
Find 199990, 219ms
Find 200000, 219ms
Find 200001, 219ms
Find 1599981, 1516ms
Find 1599982, 1516ms
Find 1599983, 1516ms
Find 1599984, 1516ms
Find 1599985, 1516ms
Find 1599986, 1516ms
Find 1599987, 1516ms
Find 1599988, 1516ms
Find 1599989, 1516ms
Find 1599990, 1516ms
Find 2600000, 2469ms
Find 2600001, 2469ms
Find 13199998, 12594ms
Find 1, 0ms
Find 199981, 47ms
Find 199982, 47ms
Find 199983, 47ms
Find 199984, 47ms
Find 199985, 47ms
Find 199986, 47ms
Find 199987, 47ms
Find 199988, 47ms
Find 199989, 47ms
Find 199990, 47ms
Find 200000, 47ms
Find 200001, 47ms
Find 1599981, 453ms
Find 1599982, 453ms
Find 1599983, 453ms
Find 1599984, 453ms
Find 1599985, 453ms
Find 1599986, 453ms
Find 1599987, 453ms
Find 1599988, 453ms
Find 1599989, 453ms
Find 1599990, 453ms
Find 2600000, 765ms
Find 2600001, 765ms
Find 13199998, 4187ms

我们以最后一个找到的数字为例,前者的时间是后者的3倍,代码的其它部分完全一样,区别就是前者是转换为字符串查找1的个数,后者使用数学的取模运算计算。

分享到:
评论
6 楼 morfil 2008-06-01  
的确String.valueOf()的效率最高
5 楼 tovegar 2007-09-25  
个人认为遇到这种问题一定要先建立数据模型!可以分析得到
if num =0  return 0
if 0<num<10 return 1
if num startWith 1 return f(10^(len(num)-1)-1)+num(去掉最高位数字)+1+f(num(去掉最高位数字))
else
10^(len(num)-1) + num(去掉最高位数字)* cal(10^(len(num)-1)-1) + f(num(去掉最高位数字));


	public static void main(String[] args) {
		// TODO Auto-generated method stub
		long start = System.currentTimeMillis(); 
		Integer num = 535200001;
		int a = cal(num);
		System.out.println("TIME = " + (System.currentTimeMillis()-start));; 
	}
	
	public static int cal(Integer num) {
		int a = 0;
		System.out.println(num);
		if (num == 0)
			a = 0;
		else if (num >=1 &&num <= 9)
			a = 1;
		else if ((num.toString()).startsWith("1")) {
			int b1 = index(10,String.valueOf(num).length() - 1) - 1;
			int b2 = Integer.parseInt(num.toString().substring(1));
			a = cal(b1) + b2 + 1 + cal(b2);
		} else {
			int b1 = index(10,String.valueOf(num).length() - 1) - 1;
			int b2 = Integer.parseInt(num.toString().substring(1));
			int b3 = Integer.parseInt(num.toString().substring(0,1));
			a = index(10,String.valueOf(num).length()-1) + b3 * cal(b1) + cal(b2);
		}
			
		return a;
	}
	
	public static int index(int number, int size) {
		int num = 1;
		for (int i=0;i<size;i++) {
			num = num * number;
		}
		return num;
	}

4 楼 orange0513 2007-08-10  
我用netbeans6.0运行上面的算法  使用number+""
Find 1, 0ms
Find 199981, 78ms
Find 199982, 78ms
Find 199983, 78ms
Find 199984, 78ms
Find 199985, 78ms
Find 199986, 78ms
Find 199987, 78ms
Find 199988, 78ms
Find 199989, 78ms
Find 199990, 78ms
Find 200000, 78ms
Find 200001, 78ms
Find 1599981, 438ms
Find 1599982, 438ms
Find 1599983, 438ms
Find 1599984, 438ms
Find 1599985, 438ms
Find 1599986, 438ms
Find 1599987, 438ms
Find 1599988, 438ms
Find 1599989, 438ms
Find 1599990, 438ms
Find 2600000, 719ms
Find 2600001, 719ms
Find 13199998, 3813ms
Find 1, 0ms
Find 199981, 47ms
Find 199982, 47ms
Find 199983, 47ms
Find 199984, 47ms
Find 199985, 47ms
Find 199986, 47ms
Find 199987, 47ms
Find 199988, 47ms
Find 199989, 47ms
Find 199990, 47ms
Find 200000, 47ms
Find 200001, 47ms
Find 1599981, 406ms
Find 1599982, 406ms
Find 1599983, 406ms
Find 1599984, 406ms
Find 1599985, 406ms
Find 1599986, 406ms
Find 1599987, 406ms
Find 1599988, 406ms
Find 1599989, 406ms
Find 1599990, 406ms
Find 2600000, 703ms
Find 2600001, 703ms
Find 13199998, 3890ms
使用String.valueOf(number);
Find 1, 0ms
Find 199981, 47ms
Find 199982, 47ms
Find 199983, 47ms
Find 199984, 47ms
Find 199985, 47ms
Find 199986, 47ms
Find 199987, 47ms
Find 199988, 47ms
Find 199989, 47ms
Find 199990, 47ms
Find 200000, 47ms
Find 200001, 47ms
Find 1599981, 281ms
Find 1599982, 281ms
Find 1599983, 281ms
Find 1599984, 281ms
Find 1599985, 281ms
Find 1599986, 281ms
Find 1599987, 281ms
Find 1599988, 281ms
Find 1599989, 281ms
Find 1599990, 281ms
Find 2600000, 453ms
Find 2600001, 453ms
Find 13199998, 2453ms
Find 1, 0ms
Find 199981, 62ms
Find 199982, 62ms
Find 199983, 62ms
Find 199984, 62ms
Find 199985, 62ms
Find 199986, 62ms
Find 199987, 62ms
Find 199988, 62ms
Find 199989, 62ms
Find 199990, 62ms
Find 200000, 62ms
Find 200001, 62ms
Find 1599981, 422ms
Find 1599982, 422ms
Find 1599983, 422ms
Find 1599984, 422ms
Find 1599985, 422ms
Find 1599986, 422ms
Find 1599987, 422ms
Find 1599988, 422ms
Find 1599989, 422ms
Find 1599990, 422ms
Find 2600000, 703ms
Find 2600001, 703ms
Find 13199998, 3891ms
字符串分析更快
3 楼 cherami 2007-07-03  
那好像还是没有数字运算快,不过还是有所提高c
2 楼 ueseu 2007-07-03  
按楼上的改了后

Find 1, 0ms
Find 199981, 63ms
Find 199982, 63ms
Find 199983, 63ms
Find 199984, 63ms
Find 199985, 63ms
Find 199986, 63ms
Find 199987, 63ms
Find 199988, 63ms
Find 199989, 63ms
Find 199990, 63ms
Find 200000, 63ms
Find 200001, 63ms
Find 1599981, 516ms
Find 1599982, 516ms
Find 1599983, 516ms
Find 1599984, 516ms
Find 1599985, 516ms
Find 1599986, 516ms
Find 1599987, 516ms
Find 1599988, 516ms
Find 1599989, 516ms
Find 1599990, 516ms
Find 2600000, 844ms
Find 2600001, 844ms
Find 13199998, 4391ms
Find 1, 0ms
Find 199981, 47ms
Find 199982, 47ms
Find 199983, 47ms
Find 199984, 47ms
Find 199985, 47ms
Find 199986, 47ms
Find 199987, 47ms
Find 199988, 47ms
Find 199989, 47ms
Find 199990, 47ms
Find 200000, 47ms
Find 200001, 47ms
Find 1599981, 297ms
Find 1599982, 297ms
Find 1599983, 297ms
Find 1599984, 297ms
Find 1599985, 297ms
Find 1599986, 297ms
Find 1599987, 297ms
Find 1599988, 297ms
Find 1599989, 297ms
Find 1599990, 297ms
Find 2600000, 484ms
Find 2600001, 484ms
Find 13199998, 2781ms
1 楼 lazy 2007-06-20  
count1里面,把
String target = number + "";
换成
String target = String.valueOf(number);

效率马上得到极大的提升。

相关推荐

    字符串面试题整理

    字符串是编程语言中常见且重要的数据结构之一,尤其在面试中常常被用来考察候选人的逻辑思维和算法理解能力。以下是一些与字符串相关的面试题目及其解题思路: 1. **字符串循环左移**:给定一个字符串和一个整数k,...

    面试题练习题前端 JavaScript高级语法-字符串属性

    面试题练习题前端 JavaScript高级语法-字符串属性面试题练习题前端 JavaScript高级语法-字符串属性面试题练习题前端 JavaScript高级语法-字符串属性面试题练习题前端 JavaScript高级语法-字符串属性面试题练习题前端...

    C语言基础面试题(03-字符串函数).docx

    以上解答了C语言中涉及字符串处理的一些基础面试题,实际编程中,我们需要考虑到边界条件、效率优化和错误处理等因素,确保代码的健壮性和正确性。在面试中,理解这些基本概念并能灵活运用是至关重要的。

    面试题,关于字符串的面试题,很详细

    字符串处理面试题总结 字符串处理是程序员日常工作中最常遇到的问题,能够体现程序员的基本功。下面是关于字符串处理的面试题总结: 一、求字符串的最小后继 问题:实现一个函数,输入一个字符串,输出该字符串的...

    2010笔面试专栏一:字符串[借鉴].pdf

    本文将基于提供的内容,深入解析两个字符串处理问题,一个是求给定字符串的最小后继,另一个是实现字符串的右移操作。 首先,我们来看第一个问题:求给定字符串的最小后继。这个问题主要考察的是对字符编码的理解和...

    1.字符串高频面试题精讲

    1.字符串高频面试题精讲1.字符串高频面试题精讲1.字符串高频面试题精讲

    C/C++字符串,字符转数字,数字转字符

    在C/C++编程语言中,字符串处理是一个非常基础且重要的知识点。C/C++语言本身并没有专门的字符串变量类型,而是使用字符数组来存放字符串,其中字符串的结束符是“\0”(空字符)。掌握字符与数字之间的转换对于进行...

    IT软件开发笔试面试题.docx

    11. 最长数字串:该题目要求编写一个函数,输出字符串中最长的数字串,考察了候选人的字符串处理能力和算法设计能力。 知识点:字符串处理、数字串识别、动态规划。 12. 字符串左旋转:该题目要求编写一个函数,...

    c语言面试题之哈希表字符串中的第一个唯一字符.zip

    综上所述,解决“C语言面试题之哈希表字符串中的第一个唯一字符”不仅要求掌握C语言的基础语法,还需理解哈希表的原理和应用,以及具备良好的算法设计和分析能力。熟练掌握这些知识点,对于提升C语言编程技能和应对...

    面试高频算法题总结-剑指Offer题解

    面试题20:表示数值的字符串 面试题21:调整数组顺序使奇数位于偶数前面 面试题22:链表中倒数第k个节点 面试题23:链表中环的入口节点 面试题24:反转链表 面试题25:合并两个排序的链表 面试题26:树的子结构 面试...

    C语言字符串练习(习题+答案).zip

    本资源"《C语言字符串练习(习题+答案).zip》"正是针对这一需求而准备的,它包含了C语言字符串操作的专项练习题和对应的答案,帮助学习者巩固和提升在字符串处理方面的技能。 字符串在C语言中扮演着重要角色,它们...

    自己总结的面试题字符串

    在C++编程中,字符串处理是面试中常见的知识点,尤其是涉及到内存操作的部分。本文将深入探讨`memset`、`strcpy`、`memcpy`以及`memmove`这四个函数的使用和区别。 首先,`memset`函数用于填充内存。它的原型是`...

    Code_笔试题_字符串压缩_

    标题中的“Code_笔试题_字符串压缩_”指的是一个与编程相关的笔试题目,重点在于实现字符串的压缩功能。这类问题通常出现在技术面试或招聘过程的笔试试题中,旨在考察应聘者的编程能力和对数据结构的理解。 描述中...

    c语言面试题之双指针反转字符串.zip

    在这个"反转字符串"的面试题中,我们将深入探讨如何使用双指针来实现这一任务。 首先,我们需要了解C语言中字符串的基本概念。在C语言中,字符串是由零个或多个字符组成的序列,以空字符'\0'作为结束标志。我们通常...

    腾讯在线笔试题-字符串反转,以及把整个字符串逆序

    首先,字符串反转是编程中常见的问题,常常用于各类笔试和面试中。而字符串逆序则是在反转的基础上,进一步处理,让整个字符串的顺序完全颠倒。 在本知识点中,将详细介绍以下内容: 1. 字符串反转的原理和方法 2. ...

    程序员面试题精选-输出一个字符串的所有子串

    在程序员的面试中,字符串操作是一项常见的考察点。本题目的核心是输出一个给定字符串的所有子串,这里我们以字符串 "abc" 为例来详细讲解解题思路和方法。 首先,我们需要理解子字符串的概念。在字符串 "abc" 中,...

    面试题今天(字符串反转)

    根据提供的文件信息,我们可以从中提炼出与字符串反转相关的知识点,具体包括以下方面: ### 字符串反转的方法 #### 方法一:使用字符数组实现反转 在第一个示例代码中,使用了字符数组来实现字符串的反转。 ```...

    KMP算法深度解析:字符串匹配的高效之旅

    7. **字符串处理问题**:如模式匹配、字符串反转等。 8. **数学问题**:涉及数学运算和逻辑的算法问题。 解决算法题通常需要对问题进行分析,选择合适的算法或数据结构,并编写出高效、清晰的代码。在面试、编程...

    关于字符串包含的问题

    【字符串包含问题】是计算机科学中常见的字符串处理问题,主要关注如何高效地判断一个较短的字符串(子串)是否完全包含在另一个较长的字符串(主串)中。以下是几种解决此类问题的方法: ### 第一节:基础方法 1....

Global site tag (gtag.js) - Google Analytics