1、两个数组a[N],b[N],其中A[N]的各个元素值已知,现给b[i]赋值,b[i] = a[0]*a[1]*a[2]...*a[N-1]/a[i];
要求:
1.不准用除法运算
2.除了循环计数值,a[N],b[N]外,不准再用其他任何变量(包括局部变量,全局变量等)
3.满足时间复杂度O(n),空间复杂度O(1)
1: private static int[] transform(int[] a, int[] b) {
;
b[b.length - 1] = 1;
; i >= 0; i--)
;
for (i = 1; i < b.length; i++)
;
for (i = 1; i < b.length; i++)
;
return b;
11: }
12:
13: private static int[] transform2(int[] a, int[] b) {
14: // S=A(0)*A(1)*A(2)……*A(N)
15: // B(I)=10lgS-lgA(I)
16: // java中math.pow函數有一定的誤差
;
b[0] = 1;
; i < a.length; i++)
;
; i >= 0; i--) {
;
}
;
26: }
2、我们把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第1500个丑数。
最简单的肯定是遍历方法,但遍历法很大的问题在于对每个数都进行判断,进行取余和除的运算了,增加了算法的复杂度。另一种解决思路为:
根据丑数的定义,丑数应该是另一个丑数乘以2、3或者5的结果(1除外)。因此我们可以创建一个数组,里面的数字是排好序的丑数。里面的每一个丑数是前面的丑数乘以2、3或者5得到的。那关键就是确保数组里的丑数是有序的了。我们假设数组中已经有若干个丑数,排好序后存在数组中。我们把现有的最大丑数记做M。现在我们来生成下一个丑数,该丑数肯定是前面某一个丑数乘以2、3或者5的结果。我们首先考虑把已有的每个丑数乘以2。在乘以2的时候,能得到若干个结果小于或等于M的。由于我们是按照顺序生成的,小于或者等于M肯定已经在数组中了,我们不需再次考虑;我们还会得到若干个大于M的结果,但我们只需要第一个大于M的结果,因为我们希望丑数是按从小到大顺序生成的,其他更大的结果我们以后再说。我们把得到的第一个乘以2后大于M的结果,记为M2。同样我们把已有的每一个丑数乘以3和5,能得到第一个大于M的结果M3和M5。那么下一个丑数应该是M2、M3和M5三个数的最小者。
new ArrayList<Integer>();
2: ugly.add(1);
3: ugly.add(2);
4: ugly.add(3);
int max = 3;
long start = System.currentTimeMillis();
7: System.out.println(start);
while (true) {
int m2 = 0;
for (Integer i : ugly) {
11: m2 = i * 2;
if (m2 > max)
break;
14: }
int m3 = 0;
for (Integer i : ugly) {
17: m3 = i * 3;
if (m3 > max)
break;
20: }
int m5 = 0;
for (Integer i : ugly) {
23: m5 = i * 5;
if (m5 > max)
break;
26: }
27: max = (m2 < m3 ? m2 : m3) < m5 ? (m2 < m3 ? m2 : m3) : m5;
28: ugly.add(max);
if (ugly.size() == 1500) {
30: System.out.println(max);
break;
32: }
33: }
long end = System.currentTimeMillis();
long consuption = end - start;
);
另外其他几种解决方案可以参考:http://www.iteye.com/topic/832545。其中:
* 1.method1是最基础的遍历,唯一的优点估计就是简单易懂。<br/>
* 2.method2,method3的思想是先人工估算范围值,将一定范围内的值乘2,3,5排重增加,不同的地方在于method2重新遍历,
* method3排序求下标<br/>
* 3.method4的思想是将已经获取的值分别遍历,乘以2,3,5,当比最大值大就停止,比较这3个数的最小值,增加到定义的有序数组中。<br/>
* 4.method5的思想是将数进行评估,评估出该数包含丑数的数量,当超过丑数要求数量时,进行2分法进行缩小范围,直至求出解。
3、有N个网页(x_j-x_i)2 +(y_j-y_i)2 + (z_j-z_i)2。请求出最大的t,使得N个网页可以聚成K类,其中每个类至少包含一个网页,且任意两个位于不同类中网页的相似度都至少为t。【并查集】
输入
第一行包含两个整数N和K,后面N行每行三列,分别为x、y、z。
输出
最大的t的值,使用四舍五入在小数点后保留六位小数。
样例输入
5 3
0.1 0.2 0.4
0.2 0.8 0.7
0.3 0.4 0.5
0.0 0.5 0.0
0.3 0.3 0.2
样例输出
0.170000
//二分+并查集
2: #include <stdio.h>
3: #include <iostream>
4: #include <string.h>
5: #include <set>
6:
7: using namespace std;
8:
int maxn = 1024 ;
int n , k , father[maxn] ;
double diff[maxn][maxn] , x[maxn] , y[maxn] , z[maxn] , mind , maxd ;
12: bool vis[maxn] ;
double precision = 1e-9 ;
14:
return mm > nn ? mm : nn ; }
return mm < nn ? mm : nn ; }
17:
int j)
19: {
20: father[i] = j ;
21: }
22:
return father[i] == i ? i : ( father[i] = find_anc(father[i]) ) ; }
24:
double pos)
26: {
int i , j , cnt ;
28: cnt = 1 ;
29: memset(vis,0,sizeof(vis));
for( i = 1 ; i <= n ; i++) father[i] = i ;
for ( i = 1 ; i <= n ; i++)
32: {
if( i != j )
34: {
if( diff[i][j] < pos ) myUnion(find_anc(i),find_anc(j));
36: }
37: }
int sth = 0 ;
for( i = 1 ; i <= n ; i++)
//j==5
41: {
42: sth++;
43: vis[j] = 1 ;
44: }
return sth >= k ;
46: }
47:
void solve()
49: {
int i , j ;
double l , r , mid ;
52: l = mind ; r = maxd ;
while ( l <= r )
54: {
55: mid = ( l+r ) / 2.0 ;
//判断mid是否可以构成K个类..
if (check(mid)) l = mid+precision ;
else r = mid - precision ;
59: }
,r);
61: }
62:
int main()
64: {
int i , j ;
,&n,&k)!=EOF)
67: {
,&x[i],&y[i],&z[i]);
69: mind = 0.0, maxd = 1.0;
for( i = 1 ; i <= n ; i++)
for( j = i ; j <= n ; j++)
72: {
73: diff[j][i] = diff[i][j] = (x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])+(z[i]-z[j])*(z[i]-z[j]);
74: // mind = get_min(mind,diff[i][j]);
75: // maxd = get_max(maxd,diff[i][j]);
76: }
77: solve();
78: }
79: }