代码风暴

#include <iostream>
#include <vector>
#include "algorithms.h"
using namespace std;
void print()
{
 cout<<" hello world"<<endl;
}
long StringToInt(char *ch) //功能测试,边界测试,负面测试(不符合常规代入参数)
{         // 前面带 ‘+’ ‘-’代表正负,还有字符中出现字母需要判断
 if(!ch) return -1;    // 就是不是数字的字符
 long num = 0;
 bool isPositive = false;
 if(*ch == '+')   //
 {
  isPositive = true;
  ++ch;
 }
 else if(*ch == '-')  //
 {
  isPositive = false;
  ++ch;
 }
 while(*ch)
 {
  if('0'<=*ch && *ch<='9') // '0'<=*ch<='9' 这样写就是 或 的关系
  {
   num = num * 10 + (*ch - '0');
   ++ch;
  }
  else
   return -1;
  
 }
 return isPositive ? num : -num ; //前面是bool 若真整体的值就是num,即前者
}
//  [9/29/2013 qingezha] 正数的开方 主要采用二分法,一个为0.0001 ,另外一个为value
// mid 为二者的平均值,如果平均值的平方大于value则mid取上一次mid和0.0001之间的平均值
float my_sqrt(float value)
{
 float low = 0.0000001;
 float high = value>1?value:value+1;
 float mid = 0.0;
 float min = 0.0;
 do
 {
  mid =(high + low)/2;
  min = mid * mid;
  if(min>value)
   high = mid;
  else
   low = mid;
 } while (abs(value - min)>=0.000001);
 return mid;
}
//  [9/30/2013 qingezha] // lowbit表示的是某个数从右往左扫描第一次出现1的位置
int lowbit(int x)//输出x 的低位中的第一个1 位置
{
 return x&~(x-1);  //x 与 负x 相与 找到
}
void find(int *arr,int len)
{
 int xor = 0;
 int flips = 0;
 for (int i=0;i<len;++i)
  xor ^= arr[i];
 // 三个数两两的异或后lowbit有两个相同,一个不同,可以分为两组 //正确
 for(int i=0;i<len;++i)
  flips ^=lowbit(xor ^ arr[i]);
 // 表示的是:flips=lowbit(a^b)^lowbit(a^c)^lowbit(b^c) 
 int b = 0;    // 假设三个只出现一次的其中一个数为b
 for(int i=0;i<len;++i)
  if(xor ^ arr[i] == flips)
   b = arr[i];
 cout<<b<<endl;
 //test/
 //int arr[] = {1,5,7,1,5,7,12,11,13}; //共 11 个
 //find(arr,9);
 //
}

//  [9/30/2013 qingezha] Union-Find 并查集
// 初始化所有的结点用整数表示,比如(0--n-1),在处理输入pair之前,他们分属于不同的组,每个结点都是孤立的
// 可以用数组表示这种关系,数组的index表示结点,而对应的值表示组号
int const NODE_NUM = 1001;
int count_set = NODE_NUM;
int arr[NODE_NUM]={0};
void UF_init()   //初始化
{
 for (int i=0;i<NODE_NUM;++i)
  arr[i] = i;
}
int find(int p)    //查找这个结点属于 哪个组
{
 if(p>=0&&p<NODE_NUM)
  return arr[p];
 else
  return -1;
}
bool connect(int p,int q)  //判断是否连接
{
 if(p>=0 && p<NODE_NUM && q>=0 && q<NODE_NUM)
  return arr[p]==arr[q];
 else
  return false;
}
int count()     //组的个数
{
 return count_set;
}
bool union_two(int p,int q) //合并2个,使之为一个组
{
 if(p>=0 && p<NODE_NUM && q>=0 && q<NODE_NUM)
 {
  if(arr[p]==arr[q])
   return true;
  else
   for(int i=0;i<NODE_NUM;++i)
    if(arr[i]==arr[p])
     arr[i] = arr[q];

  --count_set;
  return true;
 }
 else
  return false;

}

//  [10/7/2013 qingezha].给定一个源串和目标串,能够对源串进行如下操作:
// 1).在给定位置上插入一个字符
// 2).替换任意字符
// 3).删除任意字符
// 写一个程序,返回最小操作次数,使得对源串进行这些操作后等于目标串。
// 例如:源串”hello”,目标串”lleo”,则通过3次修改可以使得源串变成目标串(删除’h',删除’e',在’o'之前插入字符’e')
//也可以通过找到最长公共字串,然后2个原来串的长度和减去公共字串的长度即可
//用f[i][j]表示要修改的最少次数 源头x[1...i] 目标y[1...j],如果x[i]==y[j] 则f[i][j]=f[i-1][j-1]
//如果不同,则可以用增,删,改,分别对应的f[i][j-1]+1,f[i-1][j]+1,f[i-1][j-1]+1,
int cal_distance(const char *sta,const char *stb)
{
 if(sta == NULL || stb == NULL)
  return 0; 
 int f[10+1][5+1]={0};  //这里可以用new一个一维数组,代替栈上的二维数组,因为栈上的编译时就确定长度,堆上的运行时才确定
        //这里纯用于测试
 for (int i=0;i<11;++i)
  f[i][0]=i;    //悲剧啊,这里误写成0 了
 for (int i=0;i<6;++i)
  f[0][i]=i;    //悲剧啊,这里误写成0 了
 int temp = 0;
 for (int j=1;j<6;++j) 
 {
  for (int i=1;i<11;++i) //j<6写成了i<6,以后要小心啊
  {
   if(sta[i]==stb[j])
    f[i][j]=f[i-1][j-1];
   else
   {
    temp = min(f[i-1][j-1]+1,f[i-1][j]+1);//这里是增,删,改对应的次数
    f[i][j]=min(f[i][j-1]+1,temp);
   }
   cout<<i<<" "<<j<<" "<<f[i][j]<<endl;
  }
 }
 return f[10][5];
 
}

//  [9/30/2013 qingezha] 链表倒置 循环与递归形式
// 一般形式,1—>2->3->4 现在1<-2<-3<-4  那么改变1的next的时候需要保存指向2的指针,然后同理处理2
// 需要保存的,用直译(见词知意)的表达出来比如:pre前面,next后面,cur当前,然后循环后赋新值
LinkPtrs reverse_link(LinkPtrs root) //头指针指向的是第一个元素
{
 if(root == NULL)
  return NULL;
 LinkPtrs nextp = root->next;  //第一个结点
 LinkPtrs pre = root;   //保留前端
 LinkPtrs temp = NULL;
 LinkPtrs reverseHead = NULL;
 pre -> next = NULL;
 while(nextp->next)
 {
  temp = nextp -> next;  //先要保存下一个指针
  nextp -> next = pre;
  pre = nextp;
  nextp = temp;
 }
 nextp -> next = pre;
 reverseHead = nextp;
 return reverseHead;
}
//链表倒置,切记 方法很巧!!!!!!!!!!!!!!!!!!
LinkPtrs reverse_link_recursive(LinkPtrs root)
{
 if(root == NULL)
  return NULL;
 LinkPtrs cur,temp,revers_head;
 if(root->next == NULL)
  return root;   //链表如果只有一个结点,那么直接返回第一个
 else
 {
  cur = root;
  temp = cur -> next;  //temp 为2->3->4的头指针
  //可以认为后面的都已经倒过来了,且认为revers_head 为倒过来的链表的头指针
  //这样理解就容易多了
  revers_head = reverse_link_recursive(temp);
  temp -> next = cur;
  cur -> next = NULL;
 }
 return revers_head;
}
//  [9/30/2013 qingezha]实现一个函数,对一个正整数n,
// 算得到1需要的最少操作次数。操作规则为:如果n为偶数,将其除以2;如果n为奇数,可以加1或减1;一直处理下去。
//奇数的时候加1或减1,完全取决于二进制的后两位,如果后两位是10、00那么肯定是偶数,选择除以2,
//如果后两位是01、11,那么选择结果会不一样的,如果是*****01,那么选择减1,如果是*****11,那么选择加1,
//特殊情况是就是n是3的时候,选择减1操作。
int func(unsigned int n)
{
 if(n==1)
  return 1;
 if(n%2==0)
  return 1 + func(n/2);
 if(n==3)
  return 2;    //3到1 共2步,先-1 后除以2,
 if(n&2)
  return 1 + func(n+1);
 else
  return 1 + func(n-1);
}
//  [10/2/2013 qingezha] 数组子序列的个数,4,14,2,3和14,1,2,3都为4,13,14,1,2,3的子序列。 对于给出序列a,有些子序列可能是相同的,这里只算做1个,要求输出a的不同子序列的数量。
// 用一个数组记录出现2次或2次以上的数字,离当前数字最近的相同的数字的下标
// 比如1 2 3 4 2,一开始都为0,然后下标一次变为1 2 3 4,到新2 的时候 因为有2,所以要找到这个2的下标,才可以运算那个式子
// 所以用last_index记录数字的下标,里面是对应的arr[i],即要找的值2
#define Mod 1000000007
long sub_sequence(int *arr,int len) //整数数组不能检查越界,要已知长度
{
 long sub_arr[120] = {0};      
 int last_index[120] = {0};      //初始值这里设的好
 for (int iter=1;iter<=len;++iter)
 {
  switch(last_index[arr[iter-1]])
   {
  case 0:
   {
    sub_arr[iter] = 2 * sub_arr[iter-1]+ 1;
    break;
   }
  default:
   {
    sub_arr[iter] = 2 * sub_arr[iter-1] - sub_arr[last_index[arr[iter-1]]-1];//上一个相同的数字的下标
   }
  }
  last_index[arr[iter-1]] = iter;    //这里写错了last_index[iter-1],每一次都更新,按次序递增
 }
 return sub_arr[len];       //这里写错了 sub_arr[len-1]
 //test///
 //int arr[20] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
 //cout<<sub_sequence(arr,sizeof(arr)/sizeof(int));
 //

}
//  [10/3/2013 qingezha]已知线段长度,求覆盖最多的点数,(一个有序数组代表各个点)
int calculate_num(int *arr,int length,int seg_len)
{
 if(arr == NULL||length<=0 || seg_len<=0)
  return 0;
 int rear = length - 1;
 int front = 0;
 int max_num = 0;
 while(rear>=0)    //从最后一个点出发,依次减去前面的点的值,判断差值,然后记录点的个数
 {
  front = rear;
  while(front>=0)
  {
   if((arr[rear]-arr[front])<=seg_len)
    --front;
   else        //这里要记住,跳出循环
    break;
  }
  //换成while((arr[rear]-arr[front])<=seg_len) 更简洁
  max_num = rear-front > max_num ? rear - front : max_num;  //这里三元操作运算符
  --rear;
 }
 return max_num;
 //
 // int arr[5] = {1,2,5,6,9};
 //  cout<<calculate_num(arr,5,2);
 //
}
//  [10/3/2013 qingezha] 真没想到可以从中间向两边出发,分别比较2边是否相同,注意回文个数是偶数/奇数情况
int getpalindrome(char *arr,int len)//获取最大的回文
{
 int i = 0;
 int j = 0;
 int max = 0;
 for (i=0;i<len;++i)
 {
  for(j=1;i+j<len&&i-j>=0;++j) //回文是奇数的情况
   if(arr[i-j] !=arr[i+j])
    break;
  if(2*j-1>max)
   max = 2*j - 1;
  for (j=1;i-j>=0&&i+j+1<len;++j)   //回文长度为偶数,认为与相邻的后面相同
   if(arr[i-j]!=arr[i+j+1])
    break;
  if(i+j+1==len&&2*j + 2>max)
   max = 2*j + 2;
  if(i+j+1==len&&2*j - 2>max)    //这里j在元素不等时跳出与for中条件不满足时跳出
   max = 2*j - 2;
 }
 return max;
}
//另外一种方法是abcgoogleaba,可以进行这样的操作:#a#b#c#g#o#o#g#l#e#a#b#a#
//中间插入#或其他字符
int getpalindrome_ss(char *arr,int len)//获取回文的最大长度
{
 int len2 = 2*len + 1;
 int j = 0;
 int i = 0;
 int max = 0;
 char *str = new char[len2];
 for (int i=0;i<len;++i)
 {
  str[2*i] = '#';
  str[2*i+1] = arr[i];
 }
 str[len2-1] = '#';     //中间插入“#”
 for(i=0;i<len2;++i)
 {
  for(j=1;i+j<len2&&i-j>=0;++j) 
   if(arr[i-j] !=arr[i+j])
    break;
  if(2*j-1>max)
   max = 2*j - 1;
 }
 delete[] str;
 return max;
}
void get_n()
{
 int num = 20;   //控制输出个数
 int i = 1;
 int temp = 0;
 while(1)
 {
  if(temp%3==2&&temp%5==3&&temp%7==2)
  {
   cout<<i<<" "<<temp<<endl;
   ++i;
   if(i>num)
    break;
  }
  ++temp;
 }
}
//  [10/10/2013 qingezha]最长相同字符
int  large_same(char *arr)
{
 if(arr == NULL)
  return -1;
 int count = 0;
 int max1 = 1;
 while(*(arr+1)!=0 && *arr == *(arr+1))
 {
  ++arr;
  ++max1;
 }
 if(*(arr+1)==0)
  return max1;    //这里出口很重要!!!!可以举例,比如aabb带进去试试,看看有没返回值
 int max2 = large_same(++arr); //别忘 了 是++,就是下一个
 return max2>max1?max2:max1;
}
//  [10/10/2013 qingezha]没有重复出现的数字
unsigned int GetNotRepeatNum(unsigned int lValue)
{
 int count[10]={0};
 int temp = lValue;
 int index = 0;
 int i = 0;
 bool isfind = true;   //初始值为false 错了
 while(1)
 {
  while(lValue>0)    //这里出口1
  {
   index = lValue % 10;
   count[index]++;
   //if(count[index]>1)  //这里出口2
   // break;
   lValue = lValue/10;

  }
  for (i=0;i<10;++i)    
   if(count[i]>1)    //只要有一个就为false,就跳出
   {       //另外跳出也有i<10的可能
    isfind = false;
    break;
   }
   //else
   // isfind = true;  //这里没写,错了
  for (int i=0;i<10;++i)
   count[i] = 0;
  if(!isfind)     //通过break出口
   lValue=++temp;
  if(i==10)     //通过i<10出口
   return temp;

 }
}
//  [10/6/2013 qingezha]遍历一个文件,里面元素个数不知道,让你设计一个算法遍历一遍,等概率的随机取出一个元素
// 可以这样:设现在遍历到第 i 个元素,现在判断如果 rand()%i为0则将返回值更新为第i个元素;否则不变
char get_equal_char(char *arr)
{
 if(arr == NULL)
  return NULL;
 int i = 1;
 char re_char = arr[0];
 char *temp = arr;
 while(*arr)
 {
  if(rand()%i==0)    //这里牛逼
   re_char = arr[i-1];
  ++i;
  ++temp;
 }
 return re_char;
}

//  [10/7/2013 qingezha] 求出1…n之间的所有亲和数。
// 所谓亲和数,即存在数a和数b,a的所有真因子之和等于b,b的所有真因子之和等于a,则称a和b为一对亲和数。
// 例如220的真因子为:1、2、4、5、10、11、20、22、44、55、110,和为284;而284的真因子为:1、2、4、71、142,和正好为220。故220和284是一对亲和数。
// 现在设j 的真因子和为sum[j],那么j 可以被所有的因子整除的和为sum[j] ,其中可以整除就是关键
void print_Affsum(int n)
{
 if(n<=0)
  return;
 int *sum = new int[n+1];
 for (int i=1;i<n+1;++i)
  sum[i]=1;    //所有亲和数都有因子 1
 for (int i=2;i<n/2;++i)  //i 作为因子,所以最大也只能为 n/2
 {
  for (int j=2*i;j<n+1;j+=i)//j 为可以整除 i,所以递增为 i
  {
   sum[j] += i;
  }
 }
 int i = 1;
 while(i<n+1)
 {
  if(sum[i]<n+1&&i==sum[sum[i]])  //这里别忘记检测sum[i]的值,因为sum[sum[i]]可能越界
   cout<<i<<" "<<sum[i]<<endl;
  ++i;
 }
 delete[] sum;
}
//  [10/7/2013 qingezha]给出一个整型数组num[],和一特定值x,判断数组中是否存在一个或若干个元素之和为x,若存在则返回true,否则false。
bool is_sum(int *arr,int len,int x)
{
 if(arr==NULL||len<1)
  return false;
 if(len==1)
  return arr[0] == x;   //如果有,要么等于x,要么<= x-arr[i]
 for (int i=0;i<len;++i)
 {
  if (arr[i]==x||is_sum(arr+i+1,len-i-1,x-arr[i]))
   return true;
 }
 return false;
}
//  [10/10/2013 qingezha] 给出一个整型数组num[],对其中的每个元素,输出在它左侧且比它小的最近元素,
// 要求时间复杂度为O(n)。例如int num[]={2,4,1,3},2无左侧最近元素;4左侧最近的是2;1没有;3左侧最近的是1.(百度面试题)
//void print_each_min(int *arr,int len)
//{
//
//}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值