《学习笔记一阶段 Day--02》方向2学习 2021-05-26

方向2学习:学习剑指Offer

开始前再唠叨一点点,板砖人在外打拼一定要注意身体。今天一个在外地的同学告诉我他要动手术(老同学好多都一直单身一个人的)。也就我有空了,准备明天过去照看他一段时间。现在环境越来越恶劣,每个人压力都大,免不了要 出点小毛病。但是身体还是最重要的,最好的方法就是要多做运动。其实也没脸说别人,来深圳后真的是热的不想动,呼吸都会冒汗。坚持的跑步本来准备找个健身房去的,可是工作都没稳定下来,只能无声叹息!!!干我们这行的哪有太多时间去保养身体。。。脑阔疼

一晃快中午了,罪过罪过。

开胃例题:

#include<iostream>
using namespace std;
class TEM
{
  int a;
  public:
  TEM(int x):a(x){}
  TEM(TEM st){this->a=st.a;}//拷贝构造函数
};

int main()
{
    TEM s1(2);
    TEM s2(s1);
    return 0;
}

请问会报什么错误?

当给s2初始化的时候调用了s2的拷贝构造函数,由于是值传递,系统会给形参st重新申请一段空间,然后调用自身的拷贝构造函数把s1的数据成员的值传给st。即会产生一个TEM st(s1),是不是与开始的TEM s2(s1)很像。对的,所以会继续在st对象中使用拷贝构造,无限重复TEM st(s1)。但是当我们用&st接s1时st先当于s1的别名,不会再产生拷贝,所以就不会死循环。
也可以理解为,只要调用拷贝构造函数,就会重新申请一段空间,只要重新申请一段空间,就会调用拷贝构造函数,这样一直下去就形成了一个死循环。所以拷贝构造函数一定不能是值传递

书中推荐《Effective C++》,嗯这也算重点。

开始正式做题:
面试题1:如下类型的声名,请为该类型添加赋值运算符函数
class CMyString
{
public:
     CMyString(char*pData=nullptr);
     CMyString(const CMyString&str);
     ~CMyString(void);
private:
  char*m_pData;
}
提示:1.返回值应满足连等的赋值运算;2.为不改变传入参数的实例状态使用const;3.释放已有内存;4.传入的参数与当前实例不能是同一个,以防释放后找不到需要的赋值内容。
CMyString& CMyString::operator=(const CMyString&str)
{
     if(str!=this)//第一步判断是否需要进行拷贝
     {
CMyString temp(str);//拷贝一个临时实例
char*p=temp.m_pData;//储存实例内指针
temp.m_pData=m_pData;//讲原指针付给临时实例,用临时实例的析构释放指针,同时避免使用delet会使原指针大小变化
     m_pData=p;//将新的new char (*(str.m_pData))
     }
return *this;//返回本身,对this取*
}
思路方向除了主动思考空间释放可能造成的错误主动避免,总结出一种思维方式:当前已知变量有 赋值参数str、被赋值变量str_x。
1、其中完成赋值时需要释放被赋值变量内空间。此时我们想到delet。我们需要一个变量接受原空间坐标之后再delet(所以我们知道了还需要自定义第三个临时变量)。
2、并且str也不能直接传给str_x,必须复制一个相同的新空间给str_x,使用new是不错的选择,但是需要重新指定空间大小,用以拷贝内容。所以我们想到了使用拷贝构造创建一个CMyString temp(str)。
而上一步我们刚好需要一个变量接受需要释放的原str_x的空间(temp析构时能自动释放空间具备delet功能代替了上一步准备创建的临时变量)。
3、接下来我们只需要将temp和str_x交换便能完成赋值和释放。
定义一个指针p=temp.m_pData,再让temp.m_pData=m_pData(temp析构时释放的就是原来的m_pData),最后m_pData=p(此时p是temp.m_pData,str_x里的m_pData就等于了拷贝出来的temp.m_pData)

面试题2:设计一个类只能生成一个实例(创建一个单例)
这题在很多面试都会有,
意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
主要解决:一个全局使用的类频繁地创建与销毁。
何时使用:当您想控制实例数目,节省系统资源的时候。
如何解决:判断系统是否已经有这个单例,如果有则返回,如果没有则创建。
关键代码:构造函数是私有的
优点:
1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。
2、避免对资源的多重占用(比如写文件操作)。
缺点:没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
使用场景:
1、要求生产唯一序列号。
2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。
注意事项:getInstance() 方法中需要使用同步锁 synchronized (Singleton.class) 防止多线程同时进入造成 instance 被多次实例化。
部分内容摘取自https://www.runoob.com/design-pattern/singleton-pattern.html

书中列出了五种解法,除了第一种基础的,后面都没看懂。就我理解,单例要具备一下一个特点:
1、构造函数私有权限;2、唯一成员变量静态私有;3、公共函数调取静态成员变量;4、只有一个实例化对象。

面试题3:找出数组中重复的数字,如{2,3,4,2,5,3,1}
参考哈希表的原理,建两个数组。一个存入不重复的数字,一个存出现次数。



今日学习要点一:二分法、归并排序、动态太规划、贪婪算法

二分法:(内容摘自https://www.runoob.com/

二分搜索是一种在有序数组中查找某一特定元素的搜索算法。搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。

C 库函数 void *bsearch(const void *key, const void *base, size_t nitems, size_t size, int (*compar)(const void *, const void *)) 

对 nitems 对象的数组执行二分查找,base 指向进行查找的数组,key 指向要查找的元素,size 指定数组中每个元素的大小。

 

归并排序:(内容摘自https://www.runoob.com/

归并排序(Merge sort,台湾译作:合并排序)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。

算法步骤:

1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列

2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置

3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置

4. 重复步骤3直到某一指针达到序列尾

5. 将另一序列剩下的所有元素直接复制到合并序列尾

5550

public static void merge_sort(int a[],int first,int last,int temp[]){

  if(first < last){
      int middle = (first + last)/2;
      merge_sort(a,first,middle,temp);//左半部分排好序
      merge_sort(a,middle+1,last,temp);//右半部分排好序
      mergeArray(a,first,middle,last,temp); //合并左右部分
  }
}
//合并 :将两个序列a[first-middle],a[middle+1-end]合并
public static void mergeArray(int a[],int first,int middle,int end,int temp[]){    
  int i = first;
  int m = middle;
  int j = middle+1;
  int n = end;
  int k = 0;
  while(i<=m && j<=n){
      if(a[i] <= a[j]){
          temp[k] = a[i];
          k++;
          i++;
      }else{
          temp[k] = a[j];
          k++;
          j++;
      }
  }    
  while(i<=m){
      temp[k] = a[i];
      k++;
      i++;
  }    
  while(j<=n){
      temp[k] = a[j];
      k++;
      j++;
  }

  for(int ii=0;ii<k;ii++){
      a[first + ii] = temp[ii];
  }
}

动态太规划()空间合理分配的算法,目前只在b站找到少量视频

贪婪算法()

明天去杭州看看我那盆友,这段时间尽量不托进度吧

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值