算法总结三

来源:互联网 发布:嘉霖集团 知乎 编辑:程序博客网 时间:2024/05/16 08:11

unsigned char a=0xA5;

unsiged char b=~a>>4+1;

求b

解:unsigned char只能表示低八位,1个字节八位,这里0x表示十六进制,所以从0000到1111为16位,4位表示1位,C++中&&和 ||表示bool之间的与和或,&和 | 表示位运算的与和或,符号优先级顺序,加号大于移位运算符大于取反运算符    因此4+1=5,A5=1010 0101 右移五位=0000 0101取反=1111 1010因为b是unsigned char因此全是正的,为250


关于位运算一共有与,或,异或,左移,右移

位运算效率比除2乘2快许多,如果9与1,那么为1001&1也即为1,8与1为1000&1为0,

例题:
求出一个数的二进制中1的个数:将一个整数最后一位和1相与,然后右移一位



因为一个大于0的整数至少有1个1,那么从右往左找到第一个1,该数-1,表示该位为0,后面的位全部从0变为1,也即从右往左找到第一个1,该数-1表示该位左边不变,右边取反,注意两个取反的数相与得0,把原来的数和该数-1相与,左边部分不变,右边部分为0,



例题


1010和1101比较,我们发现都是1和都是0就不移动设为0,01和10就是移动设为1,那么是异或预算


char s[]="0123456789";      sizeof(s)=11        sizeof(*s)=1     //因为最后还有个\0位置,   

int s[100]="0123456789"   sizeof(s)=400    

数组new出的数组大小比如是char[] s=new char[2];   那么只给s[0],s[1]开辟内存,s[2]没有开辟内存


执行GetMemory(str); 

void GetMemory (char*p, int num){

  p=(char * )malloc(size of(char)*num);

}                             //这里的意思是传入str字符串为其开辟内存,但是,由于函数中形参的副本机制,没有返回指针,因此不能达到效果,每次执行一次函数就会申请一次内存,但是内存却不能有效释放,结果是内存一直被占用,造成内存泄漏


如果str为字符串,那么*str为第一个首字母而不是整个字符串的内容


c#

数组中str.length获取到的是数组初始化分配的大小,不是元素不为空的大小,因此,可以改用list,再用list.length


构造函数没有返回值,别犯二,public 函数名(){},还有static在public的后面,public static

二维数组初始化

  1.             //规则二维数组的定义和初始化  
  2.             int[,] Arr = new int[2, 5] { { 1, 2, 3, 5, 6 }, { 1, 2, 3, 4, 5 } }; 

如果二维数组初始化,指定了行和列的大小必须上面的方法,如果只是指明了行的大小,那么下面每一行都要初始化数据,根据数据大小判断多少列

  1.             //不规则二维数组  
  2.             int [][] arr = new int [3][ ];  //表示含有三个一维数组的数组 
  3.             arr[0] = new int[5]{1,2,3,4,5};  
最后一行是一维数组的初始化,把整个数组放到后面

int[] numbers = new int[5] {1, 2, 3, 4, 5};       或     int[] numbers ={1, 2, 3, 4, 5};

得到二维数组的行数和列数:

p.getlength(0);
p.getlength(1);
0代表的行数,1代表的列数
输入一个整数,输出该数二进制表示中1的个数
 public static int GetResult(int target)        {            int n = 2;  //2为底数            int res = 0; //为多少个1            while (true)     //注意递归和迭代中迭代方式必须用while(true)来作为退出条件,不能用Math.Pow(n, m)作为退出条件            {                int m = 0;  //m为幂                if(target==0){                    break;                }                while (target >= Math.Pow(n, m))                {                    m += 1;                }                target -= (int)Math.Pow(n, m-1);                res += 1;            }            return res;          }   

剑指offer:




如果错误在于


应该是如果传参传的是对象本身而不是引用会调用拷贝构造函数


1 .



3.


 

4.


最后说下return this和return *this的区别,

class A  {  public:      int x;      A* get()      {          return this;      }  };  
如果返回this,返回当前对象的地址,所以要拿A*接收

class A  {  public:      int x;      A get()      {          return *this; //返回当前对象的拷贝      }  };  
如果返回的是*this,那么返回的是对象的引用,所以要用A&或者A来接收



c# internal关键字:

只有在同一程序集的文件中,内部类型或成员才可访问


Console.WriteLine("{0}{1}")中的{0}{1}是什么意思?

Console.WriteLine("{0}{1}",1,2);
会输出 12
Console.WriteLine("{0}{1}","1234",2);
会输出 12342
{0}表示第1个输出对象,{1}表示第2个输出对象,当然如果{0},{1}那么输出的是1234,2


C#中ref和out的作用

在C#中通过使用方法来获取返回值时,通常只能得到一个返回值。因此,当一个方法需要返回多个值的时候,就需要用到ref和out

ref代码演示:

 static void Main(string[] args)        {            int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };            float avg = 0; //注意在传入ref类型的形参时,必须对它们进行初始化            int max = 0;            int min = 0;            int sum = GetIntResult(arr, ref avg, ref max, ref min);            Console.WriteLine("和:{0}\t平均值:{1}\t最大值:{2}\t最小值:{3}", sum, avg, max, min);            Console.Read();        }        static int GetIntResult(int[] arry, ref float avg, ref int max, ref int min)        {            int sum = 0;            max = arry[0];            min = arry[0];            for (int i = 0; i < arry.Length; i++)            {                sum += arry[i];                if (max < arry[i])                {                    max = arry[i];                }                if (min > arry[i])                {                    min = arry[i];                }            }            avg = sum / arry.Length;            return sum;        }

可以看到,调用完ref参数的函数,虽然返回的不是ref的参数,但是主函数仍然能把在调用函数修改后的值输出出来

out代码:

 int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };             float avg;//在使用out关键字时,不需要在此处初始化,但要在函数中初始化             int max;             int min;             int sum = GetIntResult(arr, out avg, out max, out min);
结果和上面一样。

结论:

       关键字“ref“和”out”之间的唯一区别就是关键字ref要在传参前初始化,out在函数中初始化

C#中的ref和out提供了值类型按引用进行传递的解决方案,ref和out关键字将告诉编译器,现在传递的是参数的地址而不是参数本身,现在用ref和out修饰后,传递的就是这个指针,所以可以实现修改后a,b的值真正的交换。这就是ref和out给我们带来的好处。


算法:实现一个函数,把字符串中的每一个空格替换成”%20”。

第一个种方法:遍历每一个字符(第一个for循环),当遇到空格的时候后面的数整体移动3个单位(第二个for循环),时间复杂度为n2

更好的办法是:只使用一层for循环,用另一个数组接收这个数组的每一个值,将移动数组的语句变成赋值语句,并用2个变量保存接收到2个数组当中的第i位,当接收到空格,新数组加上”%20”,i+=3;即可,时间复杂度为n


判断两个小数是否相等的时候,比如float和double类型,不能直接d1==d2,要用他俩只差的绝对值是否在一个很小的范围内


排序:

我们可以看到时间复杂度要求这么低,很直观得到需要将一部分的时间复杂度转成了空间复杂度,也即牺牲一部分内存来得到运算效率。

如果是O(n)那也就是遍历一次一个for循环,那么第一次遍历所有数,找到最大值和最小值,第二次用一个新数组,开辟大小为(最大值-最小值)。

那么第0个位置放最小值有几个,第1个位置放最小值+1有几个,遍历需要排序的数,依次记录每个数有多少个,依次放到新数组中,遍历新数组,依次输出元素>0的记为排序后的

总结:要想把时间复杂度降下来,用一个数组接收最小值到最大值之间所有可能,记录每个元素出现次数即可,


原创粉丝点击