1.重新排列数组
1.重新排列数组
很简单,把数组分别插入一个新数组就行,cpp的vector使用push_back方法更简单。
public int[] shuffle(int[] nums, int n) {
int[] res = new int[2*n];
for(int i=0;i<2*n;i+=2){
res[i]=nums[i/2];
res[i+1]=nums[i/2+n];
}
return res;
}
2.数组中的 k 个最强值
2.数组中的 k 个最强值
t2有两种思路,我这里使用的双指针,因为答案一定是从排序过后的数组两端出来的,所以用两个指针不断比较,填满答案即可。
第二种思路是基于cpp的sort方法中的重载方法,通过重写cmp方法来达到。
public int[] getStrongest(int[] arr, int k) {
Arrays.sort(arr);
int m=0,n=arr.length;
if(n%2==0){
m=(arr[n/2-1]);
}
else m=arr[n/2];
int[] res = new int[k];
int left=0,right=arr.length-1,i=0;
while(k>0){
if(Math.abs(arr[left]-m)<Math.abs(arr[right]-m)) {
res[i] = arr[right];
right--;
}
else if(Math.abs(arr[left]-m)>Math.abs(arr[right]-m)) {
res[i]=arr[left];
left++;
}
else{
if(arr[left]>arr[right]) {
res[i]=arr[left];
left++;
}
else{
res[i] = arr[right];
right--;
}
}
i++;
k--;
}
return res;
}
基于cmp的写法会简洁很多
int M;
int Abs(int x){
if (x < 0) return -x;
return x;
}
bool cmp(int a, int b){
if (Abs(a - M) != Abs(b - M)) return Abs(a - M) > Abs(b - M);
return a > b;
}
class Solution {
public:
vector<int> getStrongest(vector<int>& arr, int k) {
int n = arr.size();
sort(arr.begin(), arr.end());
M = arr[(n - 1) / 2];
sort(arr.begin(), arr.end(), cmp);
vector<int> ans;
for (int i = 0; i < k; i++) ans.push_back(arr[i]);
return ans;
}
};
3.设计浏览器历史记录
模拟题,可以用数组或者list去模拟,操作一个指针来确定当前所在的页的序号即可,细节较多,主要是防止越界和处理vistt函数,要求并不低。
class BrowserHistory {
List<String> his;
int cur;
public BrowserHistory(String homepage) {
his = new LinkedList<>();
cur=1;
visit(homepage);
}
public void visit(String url) {
while(his.size()>cur){
his.remove(his.size()-1);
}
his.add(url);
cur=his.size();
}
public String back(int steps) {
if(cur-steps<1) {
cur=1;
return his.get(0);
}
else {
int curStr = cur-steps-1;
cur=cur-steps;
return his.get(curStr);
}
}
public String forward(int steps) {
String res = new String();
if(cur+steps>his.size()){
res=his.get(his.size()-1);
cur=his.size();
}
else {
res = his.get(cur+steps-1);
cur=cur+steps;
}
return res;
}
}
4.给房子涂色 III(我还是不会,参考的大佬代码)
多维dp,分别包括了前面多少个房子用了哪些颜色形成了多少个街区。数据规模较小,和前两场的t4比较像,可以尽情写很多层for来跑dp。
这个题目的核心转移方程主要是两种情况,一种是和前面房子颜色一致时,街区数量不变,cost增加,一种是颜色不一致是,街区增加。
public int minCost(int[] houses, int[][] cost, int m, int n, int target) {
int BIG = 10000000;
int ret = -1;
int[][][] dp = new int[m][target][n];//前m个房子,多少个街区,最后一间房子的颜色的最小化费。
for(int i=0;i<m;i++){
for(int j=0;j<target;j++){
for(int k=0;k<n;k++){
dp[i][j][k]=BIG;
}
}
}
//初始化,第一个房子,切一个街区,房子颜色为,需要的最小花费
if(houses[0]==0) {
for (int k = 0; k < n; k++) {
dp[0][0][k] = (houses[0] == k + 1) ? 0 : cost[0][k];
}
}else{
dp[0][0][houses[0]-1]=0;//已经上过色不花钱
}
for(int i=1;i<m;i++){
for(int j=0;j<target;j++){
for(int k=0;k<n;k++){
if(houses[i]!=0&&k+1!=houses[i]){
continue;//该房子上过色且颜色不同
}
int costMoney = (houses[i]==k+1)?0:cost[i][k];
int ans = Integer.MAX_VALUE;//第一维是房子数,第二维是街区数,第三维是颜色
for(int h=0;h<n;h++){//之前的所有颜色遍历
if(k==h){//颜色不同相同,街区数+1
ans=Math.min(ans,dp[i-1][j][h]+costMoney);
}else{
if(j>0) {//防越界,且颜色相同
ans = Math.min(ans, dp[i - 1][j - 1][h] + costMoney);
}
}
}
dp[i][j][k]=Math.min(dp[i][j][k],ans);
}
}
}
int ans = BIG;
for(int i=0;i<n;i++){
ans = Math.min(ans,dp[m-1][target-1][i]);
}
return ans==BIG?-1:ans;
}
(我太菜了还想再ak一次周赛)