以后要坚持刷题了,太久不用C++,很生疏。还要一些计算机的基础知识,也忘得差不多了。我计划将做题过程中遇到的问题记录下来,写成系列,方便以后翻看。
几个特性:
补码的正零与负零表示方法相同;
对一个整数的补码再求补码,等于该整数自身;
正整数的补码是其二进制表示,与原码相同;
求负整数的补码,将其原码除符号位外的所有位取反(0变1,1变0,符号位为1不变)后加1。
比如-15,用八位表示,就是10001111,除了符号位都取反,就是11110000,加1就是11110001,所以-15的补码就是11110001。
找到一个方便的用法:
unsigned int a = 43261596;
bitset<32> bs(a);
cout << bs << endl;
输出是00000010100101000001111010011100,这个是LeetCode 190题的题目中的。不过这样用了bitset库,下面再用另一个方法试试。
for (int i = 0; i < 32; i++)
{
cout << ((a >> i) & 1);
}
这个的输出就和题目要求的一样的了,是二进制形式的反序列,想要正序列则要从32开始到0这么个顺序。
这个题应该是可以直接用字符串翻转头尾实现的,无需别的操作。比如:
string reverseString(string targetString)
{
string tmpString = "";
int targetStringLength = targetString.length();
for (int i = targetStringLength; i > 0; i--)
{
tmpString += targetString[i - 1];
}
return tmpString;
}
不过运行的时候发现有代码要求,就是这样的:
class Solution {
public:
uint32_t reverseBits(uint32_t n) {
}
};
所以就不能用字符串的方式了。那么题目其实描述是不准确的,不是输入二进制串,而是输入整数,如43261596,然后输出也要整数才行。那么写成这个样子:
uint32_t reverseBits(uint32_t n)
{
unsigned int tmp = 0;
for (int i = 0; i < 32; i++)
{
if (((n >> i) & 1) == 1)
{
tmp += (1 << (32 - 1 - i));
}
}
return tmp;
}
头一次在LeetCode刷题,也不用管输入输出了,不错。
LeetCode题目,序号为1的简单题:
#include
#include
using namespace std;
class Solution {
public:
vector twoSum(vector& nums, int target)
{
vector result;
vector::iterator it;
vector::iterator innerIt;
int i = 0, j = 0;
for (it = nums.begin(); it != nums.end() - 1; it++)
{
j = i + 1;
for (innerIt = it + 1; innerIt != nums.end(); innerIt++)
{
if (*it + *innerIt == target)
{
result.push_back(i);
result.push_back(j);
}
j++;
}
i++;
}
return result;
}
};
int main()
{
Solution solution;
int numsArray[] = { 2, 7, 11, 15 };
vector numsVector(numsArray, numsArray + 5);
vector::iterator it;
vector result = solution.twoSum(numsVector, 26);
for (it = result.begin(); it != result.end(); it++)
{
cout << *it << endl;
}
return 0;
}
这里可以用push_back存放结果,不过一开始数据很多的话就可以用一个数组存好然后直接给vector赋初值。
一般写for循环分三段,今天见个两段的,突然有些不太确定了,再理一下。
for (int i = 5; i--;)
{
std::cout << i << std::endl;
}
首先,一个分号是一段,两个分号分成三段,所以这段代码 i-- 是第二段,而第三段则留空了。for循环先执行第一段,比如这里 i 就是5了;然后执行第二段,这里 i 自减变成了4;然后执行函数体打印,然后执行第三段,也就是空。最终输出是4,3,2,1,0。那为什么没有继续减下去呢,比如一开始就是-5,就能一直减下去;一开始是-5自增的话也就只能到0就停止了。这是因为一般写for循环,第二段是判断如小于多少,第三段才是自增自减;而这里代码中 i-- 是有值的,它就是个布尔值了相当于。在C++中,if语句对于0就认为是假不执行,像是 -1或者正值1,2,3等就认为是真,可以执行。
引用不能为空,指针可以为空。比如:
int& a; // 错误,引用必须初始化
int n;
int& b = n; // 正确
.h头文件是旧标准,如stdio.h可以用新的:
#include
替换,就是将.h去掉并在开头添加了“c”,所以string.h就变成了cstring,含有strcpy等方法。同时,C++还有一个:
#include
这个是C++标准定义的头文件,它定义了string类型,支持字符串的size()等方法。
c++中定义了__cplusplus,而c中则没有。c语言和C++编译的函数不同,许多时候就用__cplusplus配合extern "C"的方式,让C++编译器按照c的编译格式来进行编译。
sizeof对int求大小,就是4,x86和x64都是这个结果。而sizeof对int*求大小,x86下就是4,x64下是8,也就是说,指针在x86下占用4个字节,x64下占用8个字节。因为指针是地址,4个字节和8个字节正好是对应了32位和64位寻址。
如:
int*p = a;
则输出p得到00CF840,就是a的地址,输出*p则得到123,就是a的值。
输出&p则是00F6F8F4,这个地址就是指针的地址,输出*&p得00CF840,就是a的地址。
所以输出**&p得到的就是123,即a的值,*&就是指针的引用。
常量指针,指向常量,但是指针可以修改指向别处:
const char* ptr;
指针常量,指针不能再指向别处,但地址中的值可变:
char* const ptr;
const离谁近,谁就不能修改。
如:
String& String::operator=(const String& rhs)
它的参数rhs是另一个String类型实例,但是可以在该操作符重载的时候访问其私有成员,如私有的pstr,仍然可以用rhs.pstr访问。主要就是如下几种:
a. 在C++的类的成员函数中,允许直接访问该类的对象的私有成员变量。
b. 在类的成员函数中可以访问同类型实例的私有变量。
c. 拷贝构造函数里,可以直接访问另外一个同类对象(引用)的私有成员。
d. 类的成员函数可以直接访问作为其参数的同类型对象的私有成员。