1_1.在一个数组中,求它的连续子数组的最大和,要求时间复杂度为O(n)
[1]第一个最常归的方法,时间复杂度为O(n^3)
记a[i,...,j]为数组a[]上的第i个元素到第j个连续元素构成的数组, i >= 0, j <= n;
采用枚举有方法
(1)
long getMaxSum(int* ptr, int length) {
assert(ptr != NULL && length > 0);
long ret = ptr[0];
int temp = 0;
for (int i = 1; i < length; i++) {
for (int j = i; j < length; j++) {
for (int k = i; k < j; k++) {
temp += ptr[k];
}
if (temp > ret) {
ret = temp;
temp = 0;
}
}
}
return ret;
}
(2)上述方法可稍稍修改使用时间复杂度为O(n^2)
long getMaxSum(int* ptr, int length) {
assert(ptr != NULL && length > 0);
long ret = ptr[0];
int temp;
for (int i = 1; i < length; i++) {
temp = 0;
for (int j = i; j < length; j++) {
temp += ptr[j];
if (temp > ret) {
ret = temp;
}
}
}
return ret;
}
[2]采用dp(dynamic programming)动态规划时间复杂度为O(n)
以f(n)表示前n个数中在数组ptr[]中以第n个数结尾的最大连续子序列之和
那么:f(n) = max{f(n - 1) + ptr[n], ptr[n]} n >= 1;
那么:max{f(0), f(1), ... , f(n)}即为所求
方法:
long max(long t1, long t2) {
return t1 > t2 ? t1 : t2;
}
long getMaxSum(int* ptr, int length) {
assert(ptr != NULL && length > 0);
long currentMax = ptr[0];
long allMax = currentMax;
for (int i = 1; i < length; i++) {
currentMax = max(currentMax + ptr[i], ptr[i]);
allMax = max(allMax, currentMax);
}
return allMax;
}
或者
long getMaxSum(int* ptr, int length) {
assert(ptr != NULL && length > 0);
long allMax = ptr[0];
for (int i = 1; i < length; i++) {
allMax = max(allMax, max(allMax + ptr[i], ptr[i]));
}
return allMax;
}
1_2.在一个环状数组中,求它的连续子数组的最大和,要求时间复杂度为O(n)
我们从结果出发来看,结果最后肯定是从i到j的一个数组,这有两种情况
[1]如果i < j,表明最终连续子数组的最大和,与该数组ptr[]非环状情况一样的结果,
这时求普通数组ptr[]的最大连续子数组的最大和就可以了
[2]如果i > j,表明最终连续子数组中间跨过了0,这时候从j到i组成的连续子数组和就是最小的
这时求普通数组ptr[]的总和与最小边续数组和之差即可
方法:
long max(long t1, long t2) {
return t1 > t2 ? t1 : t2;
}
long min(long t1, long t2) {
return t1 < t2 ? t1 : t2;
}
long getMaxSum(int* ptr, int length) {
assert(ptr != NULL && length > 0);
long currentMax = ptr[0];
long allMax = currentMax;
long currentMin = ptr[0];
long allMin = currentMin;
long all = ptr[0];
for (int i = 1; i < length; i++) {
currentMax = max(ptr[i], currentMax + ptr[i]);
allMax = max(allMax, currentMax);
currentMin = min(ptr[i], currentMin + ptr[i]);
allMin = min(allMin, currentMin);
all += ptr[i];
}
return max(allMax, all - allMin);
}
1_3.在一个普通数组中求最大不连续序列和
以f(n)表示前n个数中在数组ptr[]中最大不连续子序列之和
那么:f(n) = max{f(n - 1), f(n - 2) + ptr[n], ptr[n]} n >= 2;
那么:max{f(0), f(1), ... , f(n)} = f(n)即为所求
方法依然采用dp
long max(long t1, long t2) {
return t1 > t2 ? t1 : t2;
}
long getMaxSum(int* ptr, int length) {
assert(ptr != NULL && length > 0);
if (length == 1) {
return ptr[0];
}
long preMax = ptr[0];
long currentMax = ptr[1];
if (length == 2) {
return max(preMax, currentMax);
}
for (int i = 2; i < length; i++) {
long temp = currentMax;
currentMax = max(currentMax, max(preMax + ptr[i], ptr[i]));
preMax = temp;
}
return currentMax;
}
1_4.在一个普通数组中求最大连续乘积子串
以f(n)表示前n个数中在数组ptr[]中以第n个数结尾的最大连续子序列之积
以g(n)表示前n个数中在数组ptr[]中以第n个数结尾的最小边续子序列之积
那么:f(n) = max{f(n - 1) * ptr[n], g(n - 1) * ptr[n], ptr[n]} n >= 1;
同时:g(n) = min{f(n - 1} * ptr[n], g(n - 1) * ptr[n], ptr[n]) n >= 1;
那么:max{f(0), f(1), ... , f(n)}即为所求
方法:
double max(double t1, double t2) {
return t1 > t2 ? t1 : t2;
}
double min(double t1, double t2) {
return t1 < t2 ? t1 : t2;
}
double getMaxSum(double* ptr, int length) {
assert(ptr != NULL && length > 0);
double allMax = ptr[0];
double allMin = ptr[0];
for (int i = 1; i < length; i++) {
double allMaxTemp = allMax;
double allMinTemp = allMin;
allMax = max(allMaxTemp * ptr[i], max(allMinTemp * ptr[i], ptr[i]);
allMin = min(allMinTemp * ptr[i], min(allMaxTemp * ptr[i], ptr[i]);
}
return allMax;
}
1_5.在一个普通数组ptr[]长度为n中,求其中任意(n-1)个元素组成的最大乘积,不能使用乘法,要求
时间复杂度O(n)
以f(i)表示前i个元数的乘积,则f(i) = ptr[0] * ptr[1] * ... * ptr[i], i >= 0
以g(i)表示后i个元数的乘积,则g(i) = ptr[i] * ptr[i + 1] * ... * ptr[n], i >= 0
以p(i)表示除了第i个元数后剩下(n-1)个元数的乘积,则
那么f(i) = f(i - 1) * ptr[i]; i >= 1,i <= length - 1
那么g(i) = g(i + 1) * ptr[i]; i >= 1, i <= length - 2
么p(i) = f(i - 1) * g(i + 1); i >= 1, i <= length - 2
以空间换时间
double getMaxSum(double* ptr, int length) {
double f[length - 1];
double g[length - 1];
double p[length];
f[0] = ptr[0];
g[length - 1] = ptr[length - 1];
for (int i = 1; i < length; i++) {
f[i] = f[i - 1] * ptr[i];
}
for (int i = length - 2; i > 0; i--) {
g[i] = g[i + 1] * ptr[i];
}
p[0] = g[1];
p[length - 1] = f[length - 1];
for (int i = 1; i < length - 1; i++) {
p[i] = f[i - 1] * g[i + 1];
}
int ret = p[0];
for (int i = 0; i < length; i++) {
if (p[i] > ret) {
ret = p[i];
}
}
return ret;
}
1_6给定一个源字符串和目标串,通过增删改将原字符串转换为新的字符串返回最小操作数
时间复杂度为O(len(source) * len(dest));
记f(i, j)表示将字符串source[]长度为i,转换为新的字符串dest[]长度为j
所有经历的最小次数.
则f(i, j) = min{f(i - 1, j) + 1, f(i, j - 1) + 1, f(i - 1, j - 1) + source[i] == dest[j] ? 0 : 1 }
f(i- 1, j) + 1表示将源字符串尾部进行删除操作
f(i, j - 1) + 1表示将源字符串尾部进行添加操作
f(i - 1, j - 1) + 1表示将源字符和目标字符串尾部进行替换操作
方法:
int min(int t1, int t2) {
return t1 < t2 ? t1 : t2;
}
int getMinTrytime(char* source, int lenSource, char* dest, int lenDest) {
int ptr[lenSource][lenDest];
for (int i = 0; i <= lenSource; i++) {
ptr[i][0] = i;
}
for (int j = 0; j <= lenDest; j++) {
ptr[0][j] = j;
}
for (int i = 1; i <= lenSource; i++) {
for (int j = 1; j <= lenDest; j++) {
ptr[i][j] = min(
min(ptr[i - 1][j] + 1, ptr[i][ j - 1] + 1)
ptr[i - 1][j - 1] + ptr[i] == ptr[j] ? 0 : 1);
}
}
return ptr[lenSource][lenDest];
}
2_1自定义char* strcpy(char* dest, const char* str)函数
功能:
1.把src开始到含NULL结束的字符串复制到dest开台的空间
char* strcpy(char* dest, const char* str) {
assert(dest != NULL && src != NULL);
char* ret = dest;
while (*deest++ = *src++) {
//do nothing;
}
return ret;
}
2_2自定义char* strncpy(char* dest, char* src, int n)函数
1.将src开始的n个这符复制到dest指向的内存中
char* strncpy(char* dest, char* src, int n) {
assert(dest != NULL && str != NULL);
char* ret = dest;
while (n-- > 0) {
*dest++ = *src++;
}
return ret;
}
2_3自定义函数void* memcpy(void* dest, void* src, int n);
1.将src开始的n个字节内容复制到dest中去
void* memcpy(void* dest, void* src, int n) {
assert(dest != NULL && src != NULL);
char* strSrc = (char*)src;
char* strDest = (char*)dest;
void* ret = dest;
while (n-- > 0) {
*strDest++ = *strSrc++;
}
return ret;
}
2_4自定义函数char* strstr(const char* str1, const char* str2);
时间复杂度为O(len(str1) * len(str2))
1.在字符串str1中找到包含字符串str2的开始位置,并返回这个位置
char* strstr(const char* str1, const char* str2) {
int i, j, k;
for (i = 0; str1[i] != NULL; i++) {
for (j = i, k = 0; str2[k] != NULL && str2[k] == str1[j]; j++, k++) {
//do nothing
}
if (str2[k] == NULL) {
return str1[i];
}
}
return NULL;
}
3约瑟夫问题
问题描述1.n个人围成一圈,从第1个人从1开始报数每当报到m时,该人从圈中去掉,
接着从下一人从1开始报数
采用环形链表的思想
int lastRemain(int n, int m) {
list<int> members;
for (int i = 0; i < n; i++) {
members.push_back(i);
}
list<int>::iterator current = members.begin();
list<int>::iterator next;
while (members.length() > 0) {
for (int i = 0; i < m ; i++) {
current++;
if (current == members.end()) {
current = current.begin();
}
}
next = current + 1;
if (next == members.end()) {
next = current.begin();
}
members.erase(current);
current = next;
}
return current;
}
4_1.快速排序
一次分组时间复杂度为O(n);
int swap(int* t1, int* t2) {
int temp = *t1;
*t1 = *t2;
*t2 = temp;
}
int partition(int* data, int start, int end) {
//随机选择基点
int index = rand() % (end - start + 1) + start;
int small = start;
swap(&data[small], &data[end]);
for (index = start; index < end; index++) {
if (data[index] < data[end]) {
if (small < index) {
swap(&data[small], &data[end]);
}
small++;
}
}
swap(&data[small], &data[end]);
return small;
}
//快速排序的主体部份
void quickSort(int* data, int start, int end) {
int index = partition(data, start, end);
if (index > start) {
quickSort(data, start, index - 1);
}
if (index < end) {
quickSort(data, index + 1, end);
}
}
4_2最小的K个数,时间复杂度O(n)
void getMinKNumber(int* data, int start, int end, int k) {
int index = partition(data, start, end);
while (index != k) {
if (index > k) {
end = index - 1;
} else if (index < k) {
start = index + 1;
}
index = getMinKNumber(data, start, end, k);
}
}
5_1求二叉树的深度,采用递归算法
时间复杂度O(lgn)
typedef struct BinaryTreeNode__ {
void* data;
struct BinaryTreeNode__* left;
struct BinaryTreeNode__* right;
} BinaryTreeNode;
int max(int t1, int t2) {
return t1 > t2 ? t1 : t2;
}
int getTreeDepth(BinaryTreeNode* pRoot) {
if (pRoot == NULL) {
return 0;
}
int left = getTreeDepth(pRoot->left);
int right = getTreeDepth(pRoot->right);
return max(left, right) + 1;
}
5_2判断一棵二叉树是不是平衡二叉树
平衡二叉树要求所有节点的左右子树的高度差不超过1
思路:后序遍历的话,它会记录左右子树的深度,方向是左 右 中
bool isBalanced(BinaryTreeNode* pRoot, int* depth) {
if (pRoot == NULL) {
*depth = 0;
return true;
}
int depthLeft;
int depthRight;
if (isBalanced(pRoot->left, &depthLeft) &&
isBalanced(pRoot->right, &depthRight)) {
int diff = depthLeft - depthRight;
*depth = max(left, right) + 1;
if (diff >= -1 && diff <= 1) {
return true;
} else {
return false;
}
}
return false;
}
bool isBalanced(BinaryTreeNode* pRoot) {
int depth = 0;
return isBalanced(pRoot, &depth);
}
6_1.建造者模式(Builder模式)
public interface Product {
}
public interface Builder {
public Builder buildPartA();
public Builder buildPartB();
public Builder buildPartC();
public Product getProduct();
}
public class ConcreteBuilder implements Builder {
private Product product;
public ConcreteBuilder(Product product) {
this.product = product;
}
public Builder buildPartA() {
...
return this;
}
public Builder buildPartB() {
...
return this;
}
public Builder buildPartC() {
...
return this;
}
public Product getProduct() {
return product;
}
}
public class Director {
public Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public Product constructProduct(Builder builder) {
return builder.buildPartA()
.buildPartB()
.buildPartC()
.getProduct();
}
}
6_2抽象工厂模式(abstract factory)
1.抽象工厂
2.具体工厂
3.抽象产品,多个抽象产品,每个抽象产品有多个具体实物
4.具体产品
public interfact AbstractProductA {
}
public interfact AbstractProductB {
}
public class ConcreteProductA1 implements AbstractProductA {
}
public class ConcreteProductA2 implements AbstractProductA {
}
public class ConcreteProductB1 implements AbstractProductB {
}
public class ConcreteProductB2 implements AbstractProductB {
}
public interface AbstractFactory {
public AbstractProductA createProductA();
public AbstractProductA createProductB();
}
public class ConcreteFactory1 implements AbstractFactory {
public AbstractProductA createProductA() {
}
public AbstractProductB createProductB() {
}
}
public class ConcreteFactory2 implements AbstractFactory {
public AbstractProductA createProductA() {
}
public AbstractProductB createProductB() {
}
}
6_3工厂模式
1.一个工厂
2.一个抽象产品
3.多个具体产品
public interface Phone {
}
public class GSMPhone implements Phone {
}
public class CDMAPhone implements Phone {
}
public class PhoneFactory {
public Phone makeGSMPhone() {
}
public Phone makeCDMAPhone() {
}
}
6_4原型模式
1.实现Java的Cloneable接口
public class Prototype implements Cloneable {
@Override
public Object clone() {
Object object = null;
try {
object = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
7_1关于HanderThread
public class HandlerThread extends Thread {
//线程的优先级
private int mPriority;
//线程的Id
private int mTid = -1;
//每个Handler必须绑定一个Looper
private Looper mLooper;
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
//Looper.loop()执行动作之前的一个回调函数
protected void onLooperPrepared() {
}
@Override
public void run() {
mTid = Process.myTid();
//创建本线程的Looper对象
Looper.prepare();
synchornized (this) {
mLooper = Looper.mLooper();
//通知所有等待该线程的Looper对象的其它子线程,本线程的Looper对象民经就绪
notifyAll();
}
process.setThreadPriority(mPriority);
//回调用函数
onLooperPrepared();
//开始消息队列的循环
Looper.loop();
mTid = -1;
}
public Looper getLooper() {
if (!isAlive()) {
return null;
}
//如果已经开始了start()函数,需要等只到looper建好
synchronized (this) {
while(isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
public int getThreadId() {
return mTid;
}
}
8_1将一个二进制中的模式001替换为011
001:1
011:3
001 ^ 011:010:2
111:7
long replace_pattern(long inputInt) {
int andMul = 7;
int compare = 1;
int orMul = 2;
int shift = 0;
for (shift = 0; shift < 31; ) {
if (inputInt & (andMul << shift) == compare) {
inputInt |= orMul << shift;
shift += 3;
} else {
inputInt |= orMul << shift;
shift += 1;
}
}
return inputInt;
}
9_1一个8*8的格子,A在左下角,B在右下角,求A点到B点的最短路径
void getMinDistance(int row, int col, int* ret) {
if (row < 8) {
getMinDistance(row++, col);
}
if (col < 8) {
getMinDistance(row, col++);
}
if (row == 8 && col == 8) {
(*ret)++;
}
}
int getMinDistance() {
int a = 0;
getMinDistance(0, 0, &a);
return a;
}
note1
最新推荐文章于 2021-11-29 14:23:25 发布