买卖股票的最佳时机 II
假设有一个数组,它的第 i 个元素是一个给定的股票在第 i 天的价格。设计一个算法来找到最大的利润。你可以完成尽可能多的交易(多次买卖股票)。然而,你不能同时参与多个交易(你必须在再次购买前出售股票)。
思路:可以采用贪心法,只要明天的价格高于今天,那么就今天买入,明天卖出,否则今天就不买入。然后继续看后天和明天的情况,以此类推
class Solution {
public static void main(String [] args){
Solution s = new Solution();
Scanner sc = new Scanner(System.in);
int count = sc.nextInt();
int [] nums = new int[count];
for(int k=0;k<nums.length;k++){
nums[k] = sc.nextInt();
}
sc.close();
int rs = s.maxProfit(nums);
System.out.println(rs);
}
public int maxProfit(int[] prices) {
int i=0;
int j=i+1;
int max =0;
while(j<prices.length){
if(prices[i]<prices[j]){
max += prices[j]-prices[i];
}
i=j;
j++;
}
return max;
}
}
买卖股票的最佳时机 I
假设你有一个数组,其中第 i 个元素是一支给定股票第 i 天的价格。如果您只能完成最多一笔交易(即买入和卖出一股股票),则设计一个算法来找到最大的利润。
思路:股票某天买入和某天卖出所得的利润其实就是每相邻两天之间价格差值之和,那么我们就是要求价格差值之和最大的那部分,即求最大相邻子序列的和,问题转化为求数组中最大连续子序列和
假设dp[i]为以i结尾最大连续子序列的和,那么dp[i]=max{dp[i-1]+array[i],array[i]},最后dp[i]即最大利润。
买卖股票的最佳时机 III
如果只能限制两次,那么可以从i=第一天开始到最后一天遍历,左右两边分别动态规划,找出两边和的最大值,和只有一次的进行比较
只出现一次的数字
给定一个整数数组,除了某个元素外其余元素均出现两次。请找出这个只出现一次的元素。
异或相同为0,0异或其他数为该数本身
class Solution {
public static void main(String [] args){
Solution s= new Solution();
Scanner sc= new Scanner(System.in);
int count = sc.nextInt();
int [] nums = new int[count];
for(int i=0;i<count;i++){
nums[i] = sc.nextInt();
}
sc.close();
int rs = s.singleNumber(nums);
System.out.println(rs);
}
public int singleNumber(int[] nums) {
int num=0;
for(int i=0;i<nums.length;i++){
num ^=nums[i];
}
return num;
}
}
最长公共前缀
编写一个函数来查找字符串数组中最长的公共前缀字符串
思路:只要以第一个字符串为模板判断是否是第二个的子串,如果不是就将它长度从尾减少一位,继续判断直到找到子串或者匹配不到
public class Solution {
public static void main(String [] args) {
Solution test = new Solution();
Scanner sc = new Scanner(System.in);
int count = sc.nextInt();
sc.nextLine();
String[] strs = new String[count];
for(int j=0;j<count;j++) {
strs[j] = sc.nextLine();
}
sc.close();
String rs = test.longestCommonPrefix(strs);
System.out.println(rs);
}
public String longestCommonPrefix(String[] strs) {
String pre = strs[0];
for(int i=0;i<strs.length;i++) {
if(pre.length()==0) {
break;
}
while(strs[i].indexOf(pre)!=0) {
pre = pre.substring(0,pre.length()-1);
if(pre.length()==0) break;
}
}
return pre;
}
}
数数并说
数数并说序列是一个整数序列,第二项起每一项的值为对前一项的计数,其前五项如下:
- 1
- 11
- 21
- 1211
- 111221
下一项遍历前一项进行判断就可以了,要注意代码细节问题
class Solution {
public static void main(String []args) {
Solution test = new Solution ();
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
sc.close();
String rs = test.countAndSay(n);
System.out.println(rs);
}
public String countAndSay(int n) {
List<Integer> current = new ArrayList<>();
List<Integer> last = new ArrayList<>();
current.add(1);
last.add(1);
if(n==1) {
return current.toString().replaceAll("\\pP|\\s*","");
}else {
for(int i=2;i<=n;i++) {
int k=0;
int count =1;
//此处不能调用clear,因为和last同一块堆内存,会清空前面last保存的内容
current = new ArrayList<>();
while(k<last.size()) {
if(k==last.size()-1) {
break;
}else {
if(last.get(k).equals(last.get(k+1))) {
count++;
k++;
}else {
current.add(count);
current.add(last.get(k));
count =1;
k++;
}
}
}
current.add(count);
current.add(last.get(k));
last = current;
}
return current.toString().replaceAll("\\pP|\\s*", "");
}
}
}
简单的广度优先遍历
广度优先搜素如果是图,则要记录每个节点的访问状态,通过队列实现广度优先,如果每一层的元素都搜素不到满足的解,则入队列准备下一层的搜素,若搜索到,则停止搜素
public class BFS {
int [] node = {1,2,3,4,5,6};
int [] visted= new int[6];
int [][] v = {
{0,1,1,1,0,0},
{1,0,0,0,1,0},
{1,0,0,0,0,1},
{1,0,0,0,1,1},
{0,1,0,1,0,0},
{0,0,1,1,0,0}
};
public static void main(String [] args) {
BFS bfs = new BFS();
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
bfs.visted[n-1]=1;
bfs.searchBFS(n);
}
public void searchBFS(int n) {
Queue<Integer> queue = new LinkedList<>();
visted[n-1]=1;
queue.offer(node[n-1]);
while(!queue.isEmpty()) {
int number = queue.poll();
System.out.println(number);
for(int i=0;i<6;i++) {
if(v[i][number-1]==1) {
if(visted[i]!=1) {
queue.offer(node[i]);
visted[i]=1;
}
}
}
}
}
}
DFS
深度优先搜素从节点的第一个分支开始搜素,继续递归搜素直到完成或超出深度
public class DFS {
int [] node = {1,2,3,4,5,6};
int [] visted= new int[6];
int [][] v = {
{0,1,1,1,0,0},
{1,0,0,0,1,0},
{1,0,0,0,0,1},
{1,0,0,0,1,1},
{0,1,0,1,0,0},
{0,0,1,1,0,0}
};
public static void main(String [] args) {
DFS dfs = new DFS();
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
dfs.searchDFS(n);
}
public void searchDFS(int n) {
if(visted[n-1]==0) {
visted[n-1]=1;
System.out.println(node[n-1]);
}else if(visted[n-1]==1){
return;
}
for(int i=0;i<6;i++) {
if(v[i][n-1]==1) {
searchDFS(i+1);
}
}
}
}
KMP算法
字符串字串的寻找
关于KMP算法,可以参考http://www.cnblogs.com/yjiyjige/p/3263858.html
import java.util.Scanner;
class TestKmp {
int [] next;
public static void main(String [] args){
TestKmp s = new TestKmp();
Scanner sc = new Scanner(System.in);
String str1 = sc.nextLine();
String str2 = sc.nextLine();
sc.close();
s.getNext(str2.toCharArray());
int rs = s.strStr(str1,str2);
System.out.println(rs);
}
//kmp
public int strStr(String haystack, String needle) {
int i=0;
int j=0;
char [] hay = haystack.toCharArray();
char [] need = needle.toCharArray();
while(i<hay.length && j<need.length){
if(j==-1||hay[i]==need[j]){
i++;
j++;
}else{
j=next[j];
}
}
//注意j==length
if(j==need.length){
return i-j;
}else{
return -1;
}
}
public void getNext(char [] child){
next = new int[child.length];
next[0]=-1;
int k=-1;
int m=0;
//注意数组溢出问题,每次都是赋值当前索引所在后面的元素
while(m<child.length-1){
if(k==-1||child[k]==child[m]){
k++;
m++;
next[m] = k;
}else{
k=next[k];
}
}
for(int l=0;l<next.length;l++) System.out.println("next[j]:"+next[l]);
}
}
从数组中找出差值为k的数对的数量,不包括重复组
比如: 1 5 3 3 1 result=2 {1,3} {3,5}
思路:先将数组排序,再将前面的数和后面比较,相等退出本层循环,继续拿第二个数和后面比较,注意如果第二个数比较前发现与第一个相等,则没有继续比较的必要,跳过本次循环,继续下一个数与后面的比较
public class Main {
public static void main(String []args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int k = sc.nextInt();
int [] nums = new int[n];
for(int m=0;m<n;m++) {
nums[m] = sc.nextInt();
}
sc.close();
Arrays.sort(nums);
int sum = 0;
int i=0;
while(i<n-1){
if(i>0&&nums[i]==nums[i-1]) {
i++;
continue;
}
for(int j=i+1;j<n;j++) {
if((nums[j]-nums[i])==k){
sum++;
i++;
break;
}
}
}
System.out.println(sum);
}
}