代码改变世界

随笔分类 -  编程之美

求点是否在三角形内

2011-09-06 23:37 by x_feng, 394 阅读, 收藏,
摘要: 问题:在一个屏幕上如何判断一次点击,在一个三角形的按钮内?解决方法:在编程之美上提供了2种方法,一种是求面积的方法,一种是点关系的矢量方法。其实两种方法的代码实现几乎相同,但考虑到效率问题,矢量法比较合适。在求面积的方法中用到了除法和开平方运算,矢量法却没有,但它有一个非常要注意的地方,即三角形的三个顶点必须是按逆时针顺序方向排列传入函数体。矢量法:如果一个点在三角形内,则按照逆时针方向,这个点都在3条边的左边。判断一个点D,是否在一条射线a,b的左边,可以通过a->b,a->D两个向量叉积的正负来判断,叉积为正D在ab的左边,叉积为0在射线ab上,否则在外。具体代码如下:#inc 阅读全文

Programe_Of_Beauty:2.17 数组循环位移

2011-06-12 17:29 by x_feng, 161 阅读, 收藏,
摘要: 问题:把一个N个元素的数组循环右移K位,要求时间复杂度为O(N)。解析:如abcd1234右移4位 要变成1234abcd1,逆序排列abcd->dcba12342,逆序排列1234->dcba43213,逆序排列dcba4321代码如下:void Reverse(int * arr, int beg, int end){ for (; beg < end ; beg++, end—) { int temp = arr[beg]; arr[beg] = arr[end]; arr[end] = temp; }}void RightSift(int* arr, int N, i 阅读全文

Programe_Of_Beauty:2.16 求数组中最长递增子序列

2011-06-12 14:05 by x_feng, 180 阅读, 收藏,
摘要: 问题:写一个时间复杂度尽可能低的程序,求一个一维数组中最长递增子序列的长度。如1,-1,2,-3,4,-5,6,-7.最长递增子序列:1,2,4,6或者-1,2,4,6… 分析:我们发现2前面是1或者-1对后面没有影响。用i来遍历数组。i=0时,arr[i] = 1就一个数,这时最长递增子序列为{1},i=1时,-1<1所以对-1来说,目前最长递增子序列为{-1}为1,i= 2时,2>1,2>-1对2来说,最长递增子序列为{1,2}或{-1,2}长度为2,当i = 3时,-3小于1,-1,2.所以当前最长子序列依然是{1,2}或{-1,2}长度为2,当i= 4时,4>- 阅读全文

Programe_Of_Beauty:2.13 子数组的最大乘积

2011-06-12 00:07 by x_feng, 223 阅读, 收藏,
摘要: 问题:给定一个长度为N的整数数组,只允许用乘法,不用除法,计算任意N-1个数的组合中乘积最大的一组。具体思想不再赘述,代码如下:#ifndef _SUB_ARRAY_MAX_MULTIPLY_H_#define _SUB_ARRAY_MAX_MULTIPLY_H_#include <iostream>using namespace std;//方法一void SubArryMaxMultiply_Calculate(int* array, int size){ if (NULL == array) { return; } int* a = new int[size]; int* b 阅读全文

Programe_Of_Beauty:2.12 快速寻找满足条件的两个数

2011-06-11 23:09 by x_feng, 177 阅读, 收藏,
摘要: 问题:能否快速找出数组中两个数字,让这两个数字之和等于一个给定的值,为了简单起见,假设这个数组中肯定存在至少一组符合要求的解。解法一:用两层循环,时间复杂度为O(N*N),不可取。解法二:先用快速排序,然后从两端向中间找,时间复杂度为O(Nlog2N)。代码如下:int Partion(int* arr, int p, int r){ int temp; int i = p; int j = r; temp = arr[i]; do { while(arr[j] >= temp && i < j) { j--; } if (i < j) { arr[i++] 阅读全文

Programe_Of_Beauty:2.4 1的数目

2011-06-11 18:02 by x_feng, 202 阅读, 收藏,
摘要: 问题:给定一个十进制正整数N,写下从1到N的所有整数,然后数一下其中出现的所有1的个数。书上解法一:最简单的方法从1遍历每一个数,算算每个数中1出现的次数,具体代码如下: 1: unsigned int countInteger(int n) 2: { 3: unsigned int num = 0; 4: while(n != 0) 5: { 6: num += (n % 10 == 1) ? 1:0; 7: n /= 10; 8: } 9: return num; 10: } 11: void OneNumber(unsigned int n) 12: { 13: unsigned int 阅读全文

Programe_Of_Beauty:2.3 寻找发帖“水王”及扩展问题

2011-06-06 15:44 by x_feng, 251 阅读, 收藏,
摘要: 问题:其实问题可以简单的说:有一个数组,数组中的某个元素出现的次数超过N/2。问有没有很好的方法快速找到这个元素。解析:如:char ID[5] = { ‘a’,‘b’,‘a’,‘c’,‘a’};a的出现次数为3。一个很高效的方法就是:当两个元素不相同时就把这两个元素都删除,这样最后剩下的就是要找的元素,当然不一定是真的删除。#ifndef _2_3_TANGO_H_#define _2_3_TANGO_H_//2.3寻找发帖水王 p129#include <iostream>//本题目的含义是,在一个序列中寻找出现次数最多的id,如a,a,b,c,a,b,a,a 当然a出现次数最 阅读全文

Programe_Of_Beauty:2.2 不要被阶乘吓到

2011-06-06 13:54 by x_feng, 243 阅读, 收藏,
摘要: 问题1:给定一个整数N,那么N的阶乘N!末尾有多少个0呢?例如:N=10,N!=3628800,末尾有2个0.问题2:求N!的二进制表示中最低位1的位置?问题1书上的解析一:例如N=10,我们发现这个数中5*2=10,如N=100呢?5*20=100,5*4=20,…如果一个数中有几个5那么这个数就贡献几个0.只要计算N!中出现多少次5就能确定末尾有多少个0.num = 0;for (int i = 1; i <=N; i++)//计算阶乘中每一个数中5出现的次数{ int j = i; while(j %5 == 0)//说明能被5整除,有一个5 { num++; j = j/5; } 阅读全文

Programe_Of_Beauty:2.1 求二进制数中1的个数(一点我的想法)

2011-06-06 01:57 by x_feng, 242 阅读, 收藏,
摘要: 对于一个字节(8bit)的无符号整型变量,求其二进制表示中的1的个数。先看看书上给出的解法:解法一:以二进制0000 1010为例,其值为10。10除以2 = 5,其二进制为0000 0101,5除以2 = 2,其二进制为0000 0010.我们发现每除2,二进制向右移了一位。当二进制的最后一位为0时,是偶数,当二进制最后一位为1时是奇数。这样我们就可以不停除2,每一个1都会移到最后的时候。2除不尽说明最后位为1.int count(BYTE v){ int num = 0; while(v) { if (v%2 == 1)//最后一位是1 { num++ ;} v = v/2; }}解法二: 阅读全文

Programe_Of_Beauty:2.10 寻找数组中的最大值和最小值

2011-05-31 21:43 by x_feng, 230 阅读, 收藏,
摘要: 1.问题定义对于一个由N个整数组成的数组,需要比较多少次才能把最大和最小的数找出来呢?2.编程之美解法解法一,遍历数组一次,分别比较,最大最小值,比较次数为2*N。解法二,遍历数组,每两个进行比较,小的放前面,大的放后面,如a[0]和a[1]比较,如果a[1]大,则交换,比较N/2次。这样,最大数在偶数位上,最小数在奇数位上,然后再各比较N/2次,共比较1.5N次。但是该方法改变了原有的数组结构,数据有变动。解法三,设置两个变量Max,Min。遍历数组,每两个数据进行比较,大的再跟Max比较,小的跟Min比较,共1.5N次。似乎是最少的比较次数了。具体实现如下:void FindArrayMa 阅读全文

Programe_Of_Beauty:3.10 分层遍历二叉树(另一种实现方法)

2011-05-30 19:41 by x_feng, 302 阅读, 收藏,
摘要: 1.问题定义给定一棵二叉树,要求按分层遍历该二叉树,即从上到下按层次访问该二叉树(每一层将单独输出一行),每一层要求访问的顺序为从左到右,并将节点依次编号。下面是一个例子: 正确输出为:12 34 5 67 8节点定义:struct Node { Node *pLeft; //节点数据 Node *pRight; //左指针 int data; //右指针};2.编程之美解法书上举出两个解法。第一个解法是用递归方式,搜寻并打印某一层的节点,再打印下一层的节点。这方法简单但时间效率不高(但不需要额外空间),因此书中亦提供了第二个解法。 书中第二个解法,使用vector容器来储存n个节点信息,并用 阅读全文

Programe_Of_Beauty :3.9 重建二叉树

2011-05-29 15:30 by x_feng, 225 阅读, 收藏,
摘要: 1.问题定义对于二叉树的3中遍历方法,相信大家耳熟能详。那么如果我们知道了其中的两种遍历结果,能不能把一棵二叉树重新建立起来?给定一棵二叉树,假设每个节点都用唯一的字符来表示,没有重复。结构如下:struct _Node{ _Node* Lchild; _Node* Rchild; char data;};假设已有了前序遍历和中序遍历的结果,希望通过一个算法来重建这棵树。前序遍历:a, b, d, c, e, f 显然a是根节点中序遍历:d, b, a, e, c, f a前面的d, b是a的左子树中的节点,a后面的e, c, f是a右子树中的节点重建后的图如下: 2.分析与解法不难发现a是前 阅读全文

Programe_Of_Beauty:3.8 求二叉树中节点的最大距离

2011-05-28 19:15 by x_feng, 258 阅读, 收藏,
摘要: 1.问题定义定义距离为两个节点之间边的个数。写一个程序求一棵二叉树中相距最远的两个节点之间的距离。下面是两个例子: 上图中列出了二叉树中节点间距离最大的所有可能情况。箭头所指的边标示了A、B之间最大的距离。2.问题分析从上图中可以看出,距离最远的两个点一定有一个共同的“根”节点,或者其中一个就是根节点(注意前者的“根”与后者的根的区别,前者的“根”包含后者)。因此只要能计算出所有“根”的左子树的最深长度和右子树的最深长度,就可以知道经过此“根”节点的所有路径中的最大距离。通俗的讲,就是计算任意一个节点的左右子树的最深长度。3.递归算法树节点的结构体定义:struct _Node{ _Node 阅读全文