三道题 2015.8.26

1:二进制中1的个数

第一种做法:最直接的将数对二作除法和余数操作。统计余数中1的个数

第二种做法:将该二进制数和1做与运算,然后再右移操作。

但是这里有一个问题就是右移运算符,将最右边的几位丢弃。并且容易陷入死循环,剑指offer第79页专门提出这个问题并给出了解释

如果数字是一个无符号数,则用0填充最左边的n位,如果数字是一个有符号的数字,则用数字的符号位填补最左边的n位。

第三种做法也是我认为最好的做法:将该整数与减去1之后得到的数做与运算。

int c = 10;

System.out.println(Integer.toBinaryString(c));

  

2:给定一个数组,知道该数组中有一个数出现的次数超过整体的一半,找出这个数

排序数组的中位数一定是这个数,而如果完全排序,会耗费很多的时间。而针对快速排序,每一趟都能确定一个元素的最终位置。

首先快速排序的算法一定要掌握:下面附上代码:

//确定一趟排序元素的位置
public static int identityTheIndex (int[] A,int low,int high){

		int key = A[low];
		while(low<high){
			while(low<high&&A[high]>=key){
				high--;
			}
			A[low] = A[high];
			while(low<high&&A[low]<=key){
				low++;
			}
			A[high] = A[low];
		}
		A[low]=key;
		return low;

	}

递归进行排序
public static void quictSort(int[] A,int low, int high){
		if(low <high){
			int index =  identityTheIndex(A,low,high);
			quictSort(A,low,index-1);
			quictSort(A,index+1,high);
		}
	}

  受到快速排序的启示,可以边排序边判断,代码如下:

public static int moreThanHalfNumber(int[] A,int length){
		int mid = length >> 1;
		int high = length - 1;
		int low = 0;
		int index = identifyTheIndex(A,low,high);
		while(index!=mid){
			if(index>mid){
				high = index - 1;
				index = identifyTheIndex(A,low,high);
			}
			else{
				low = index + 1;
				index =identifyTheIndex(A,low,high);
			}
		}
		int result = A[mid];
		return result;

	}

  第二种方法:考虑遍历数组的时候保存两个值:一个是数组中的一个数字,一个是次数,当遍历下一个数字的时候,如果下一个数字和之前保存的数字相同,则次数加1,如果下一个数字和之前保存的数字不同,则次数减1,如果次数为0,则需要保存下一个数字,并把次数设为1.由于要找的数字出现的次数比其他所有数字出现的次数之后还要多,那么要找的数字肯定是最后一次把次数设为1时对应的数字。代码如下:

public static int moreThanHalfNumber2(int[] A,int length){
		int result = A[0];
		int time = 1;
		for(int  i = 1;i<length;i++){
			if(time == 1){
				result = A[i];
				time = 1;
			}
			else if(result == A[i]){
				time ++ ;
			}
			else{
				time -- ;
			}
		}
		return result;
	}

  3:最小(大)的k个数

这道题可以借助上题的思想主要确定第K个元素的位置,最直接的想法就是快速排序。

第二种方法特别适合处理海量数据,首先创建一个大小为K的数据容器来存储最小的K的数字,接着每次从输入的n个数中读入一个数,如果容器中已有的数字少于K个,则直接读入;如果已经有K个,也就是容器已满,这时只能替换。首先要找出这K 个数字中的最大的数,如果接下来的数字小于最大的数将替换,否则继续遍历下一个数

因此,容器满了需要做3件事:

1)K个整数中找出最大的数

2)有可能在这个容器中删除最大数

3)有可能要插入一个新的数字

如果用二叉树来实现这个数据容器,就能在O(logk)时间内完成,对于n个输入数字而言,总的时间效率就是O(nlogk)

很容易想到最大堆。

下面先复习一下建堆,以及堆排序的过程。

建堆:从下向上,建好的堆,根节点最大或最小。代码如下:

public static void createMaxdHeap(int[] data, int lastIndex) {
        for (int i = (lastIndex - 1) / 2; i >= 0; i--) {
            // 保存当前正在判断的节点
            int k = i;
            // 若当前节点的子节点存在
            while (2 * k + 1 <= lastIndex) {
                // biggerIndex总是记录较大节点的值,先赋值为当前判断节点的左子节点
                int biggerIndex = 2 * k + 1;
                if (biggerIndex < lastIndex) {
                    // 若右子节点存在,否则此时biggerIndex应该等于 lastIndex
                    if (data[biggerIndex] < data[biggerIndex + 1]) {
                        // 若右子节点值比左子节点值大,则biggerIndex记录的是右子节点的值
                        biggerIndex++;
                    }
                }
                if (data[k] < data[biggerIndex]) {
                    // 若当前节点值比子节点最大值小,则交换2者得值,交换后将biggerIndex值赋值给k
                    swap(data, k, biggerIndex);
                    k = biggerIndex;
                } else {
                    break;
                }
            }
        }
    }

  堆排序:将建好的堆根节点输出,然后将其与最后一个叶子节点交换,然后重新建堆,这个时候建堆的元素个数少一。

代码如下:

 public static void heapSort(int[] data) {
        for (int i = 0; i < data.length; i++) {
            createMaxdHeap(data, data.length - 1 - i);
            swap(data, 0, data.length - 1 - i);
            print(data);
        }
    }  

public static void swap(int[] data, int i, int j) {
        if (i == j) {
            return;
        }
        data[i] = data[i] + data[j];
        data[j] = data[i] - data[j];
        data[i] = data[i] - data[j];
    }

  而这道题只是要求找出最小的K个数并没有要求有序,因此可以借助建堆的操作,代码如下:

public static void createMaxdHeap(int[] data, int lastIndex) {
        for (int i = (lastIndex - 1) / 2; i >= 0; i--) {
            // 保存当前正在判断的节点
            int k = i;
            // 若当前节点的子节点存在
            while (2 * k + 1 <= lastIndex) {
                // biggerIndex总是记录较大节点的值,先赋值为当前判断节点的左子节点
                int biggerIndex = 2 * k + 1;
                if (biggerIndex < lastIndex) {
                    // 若右子节点存在,否则此时biggerIndex应该等于 lastIndex
                    if (data[biggerIndex] < data[biggerIndex + 1]) {
                        // 若右子节点值比左子节点值大,则biggerIndex记录的是右子节点的值
                        biggerIndex++;
                    }
                }
                if (data[k] < data[biggerIndex]) {
                    // 若当前节点值比子节点最大值小,则交换2者得值,交换后将biggerIndex值赋值给k
                    swap(data, k, biggerIndex);
                    k = biggerIndex;
                } else {
                    break;
                }
            }
        }
    }  

	public static void print(int[] data) {
        for (int i = 0; i < data.length; i++) {
            System.out.print(data[i] + "\t");
        }
        System.out.println();
    }    

public static int[] getFirstNumber(int[] A, int k){

		int[] B = new int[k];
		for(int i =0;i<k;i++){
			B[i] = A[i];
		}
		heapSort(B);
		int count = k;
		while(count!=A.length){
			/*int minmumValue = B[0];
			int maxmumValue = B[k-1];*/
			int maxmumValue = B[0];
			//System.out.println("对排序后最小的元素:"+minmumValue);
			if(maxmumValue>A[count]){
				int temp = A[count];
				B[0] = temp;

			}
			System.out.println("替换元素之后的B:");
			print(B);
			System.out.println("......................................");
			heapSort(B);
			count++;
		}
		return B;
	}

public static void main(String[] args) {

		int[] A = {80,55,45,7,8,6,3,10,2,1};
		int k = 4;
		int[] C = getFirstNumber(A,k);
		System.out.print("最xiao的K个数为:");
		for(int i = 0;i<k;i++){
			System.out.print(C[i] + "\t");
		}
}

程序的输出结果为:
80	55	45	7
80	55	45	7
80	55	45	7
80	55	45	7
替换元素之后的B:
8	55	45	7
......................................
55	8	45	7
55	8	45	7
55	8	45	7
55	8	45	7
替换元素之后的B:
6	8	45	7
......................................
45	8	6	7
45	8	6	7
45	8	6	7
45	8	6	7
替换元素之后的B:
3	8	6	7
......................................
8	7	6	3
8	7	6	3
8	7	6	3
8	7	6	3
替换元素之后的B:
8	7	6	3
......................................
8	7	6	3
8	7	6	3
8	7	6	3
8	7	6	3
替换元素之后的B:
2	7	6	3
......................................
7	3	6	2
7	3	6	2
7	3	6	2
7	3	6	2
替换元素之后的B:
1	3	6	2
......................................
6	3	1	2
6	3	1	2
6	3	1	2
6	3	1	2
最xiao的K个数为:6	3	1	2

  

时间: 2024-10-14 13:17:07

三道题 2015.8.26的相关文章

周日学习内容(2015.7.26)

周日学习内容(2015.7.26) 一.流程控制初步 流程控制结构:顺序结构,选择结构,循环结构. 二.逻辑运算符 &&:逻辑与(表达式1&&表达式2 同真为真,其余为假). ||:逻辑或(表达式1&&表达式2 有真必真,其余为假). !:逻辑非(取反) 三.if-else选择结构 语法: if(){ }else{ } 四. java中产生随机数方法 范围:从0到1,能取到0,但是取不到1 五.多重if选择结构 if(表达式1){ 语句1 }else if(

【谜客帝国】第18届枫岩风羽&#183;骆岩2006年旧作谜会(2015.3.26)

[谜客帝国]第18届枫岩风羽·骆岩2006年旧作谜会(2015.3.26)主持:瓷     计分:晶莹1.“虚怀应无波”  (面积单位)  平方寸 [谜面出自现代抱朴子诗<感怀一首>]2.拂晓明霞笼禁宫  (五字唐诗目) 早发白帝城3.“樽前白首翁”      (三字食品) 干粉丝 [谜面出自唐代白居易诗<筝>]4.拖延发言心不怪 (外国节日)  圣诞5.“不断尘中一柱烟” (三字口语) 土老冒6.润之动身巧装扮  (四字影视用语) 毛发化妆7.“鸟鸣山馆客思乡”(四字广告词) 

c语言自加自减三道题

int  x , y,z; x = 0; y = z = -1; x += -z ---y; printf("x=%d\n",x) x = 2 为什么? x  + = -z - - -y 相当于 x = x + ((-z)--)-y; 这里-z-是先用-z然后再(-z)- -运算 这里需要注意的是操作符结合的顺序是自左至右,而运算顺序是自右至左! 也就是 –z - - -y 表示的是 ((-z)--)-y 而不是 (-z)-(--y) #include <stdio.h>

##老版本项目-&gt;Xcode7+Swift2.0项目改动可能遇到的问题 &gt; 维护者:PMST &gt; 最后更新日期:2015.6.26 &gt; 版本号:V1.0.0 &gt; Note:倘若

老版本项目->Xcode7+Swift2.0项目改动可能遇到的问题 维护者:PMST 最后更新日期:2015.6.26 版本号:V1.0.0 Note:倘若你的项目转换到swift2.0语法,或多或少会遇到一些问题,该文档因此诞生.鼓励大家一起参与进来,帮助国内Swift的开发和维护. github项目所属:swift2.0_PlaygroundStudyNote 团队博客地址:Optional Swift 个人博客地址:Colourful Code Error Information How

Daily Scrumming* 2015.10.26(Day 7)

一.总体情况总结 从今天开始,我们开始正式进入紧锣密鼓的集中开发周啦~~加油Fighting~ 开会讨论了一下各个人的细致分工,前端后端各自想成员分派任务. 继续各自领域的准备工作,同时开始进行开发. 二.今明两天任务表 Member Today’s Task Tomorrow’s Task 江昊 继续完善整体项目规划与成员分工,分配每个人具体任务与目标. 组织整个项目,分析技术方向 杨墨犁 设计Logo,完善页面 继续优化UI,学习html 付帅 同步进行html和css的学习,一同简单实现了

我关注的一周技术动态2015.7.26

容器技术 1. Docker持续部署图文详解 http://mp.weixin.qq.com/s?__biz=MjM5MDE0Mjc4MA==&mid=208550161&idx=1&sn=e1bdb3d219c110c79850f43c0fe1d297&key=c76941211a49ab5870652c78bff255aa29b56abb1fbd503a3584dea04af2275000a4e796fee253975115f33b11f203b1&ascene

2015/9/26,中秋前一天

最近一直听到各个学长学姐拿到腾讯,百度,阿里的offer,都是拿着年薪十几二十万的工资,我又开始怀疑自己了,我呢?明年这个时候的我应该是什么样的呢?宿舍六个妹子,除了我,基本都选择了考研,理由都是”我什么都不会,出去干什么嘛?“,是啊,已经大三了,我web开发还只是会做普通的网页,javascript看了一个多月了,还只是会做最普通的事件.这样下去,这样的我真的可以找到一份对得起自己的工作吗? 不过,有个学长很鼓励我,他一直就是自学,到大三的时候,水平也很菜,但是他并没有因此就乱了阵脚,只是按部

《笨办法学python第三版》习题26,原错误代码及正确代码

#import ex25 1 def break_words(stuff): 2 """This function will break up words for us.""" 3 words = stuff.split(' ') 4 return words 5 6 def sort_words(words): 7 """Sorts the words.""" 8 return sor

2015.10.26 信息系统项目管理师作业

一.PMI权限(授权)管理基础设施1.访问控制包括哪2个重要过程,及内容: 答: a.认证过程:通过"鉴别"来检验主体的合法身份b.授权管理:通过"授权"来赋予用户对某项资源的访问权限 2.简述PMI与PKI有何不同? 哪个是"你能做什么",哪个是"你是谁" 答: PMI:你能做什么,主要是授权PKI:你是谁,身份鉴别 二.信息安全审计系统1.中华人民共和国国家标准-计算机系统安全保护能力的5个等级: 答: 1>自主保护