走进现代通信
香农-韦弗模式
构建了一个直线单向的框架,描述了一般化的通信系统的信息传播过程。此模式包含了信源、发射器、信道、噪声、接收器、信宿6个部分。
- 信源与信宿:信源即信息的源头;信宿即信息的归宿,是接收信息的实体。这两个概念是相对的,在不同的场景下可以发生转换,例如,收音机接收电台信号时是信宿;发出节目声音时是信源,此时听收音机的人则成了信宿。
- 发射器与接收器:编码和解码。
- 信道和噪声:
- 通信方式:双工、半双工、单工。
当代通信
3G
分为WCDMA、cdma2000、TD-SCDMA
WCDMA和cdma2000属于频分双工方式(FDD),而TD-SCDMA属于时分双工方式(TDD)。WCDMA和cdma2000是上下行独享相应的带宽,上下行之间需要一定的频率间隔做“隔离带”以避免干扰;TD-SCDMA则上下行采用同一频谱,上下行之间需要时间间隔做”红绿灯“以避免干扰。
4G
LTE
LTE系统引入了正交频分复用(OFDM,orthogonal frequency division multiplexing)和多输入多输出(MIMO),显著提高了频谱效率和数据传输速率。
根据双工方式的不同,LTE系统分为FDD-LTE和TDD-LTE。二者技术的主要区别在于空口的物理层上(例如,帧结构、时分设计、同步等)。FDD空口上下采用成对的、不同的频段接收、发送数据,而TDD系统上下行使用相同的频段在不同的时隙上传输,TDD比FDD有着更高的频率利用率。
LTE-A:
LTE-A采用了载波聚合(CA,Carrier Aggregation)、上/下行多天线增强、多点协作传输、中继、异构网干扰协调增强等关键技术,能大大提高无线通信系统的峰值数据速率、峰值频谱效率、小区平均频谱效率以及小区边界用户性能。所谓多载波聚合,就是将多个频段的网络信号聚合起来,相当于公路从“单车道”变为了“多车道“。
5G
根据3GPP的定义,5G的三大应用场景为eMBB、mMTC、URLLC。eMBB即为增强移动宽带,超高速,为大流量移动宽带业务提供支持;mMTC指海量机器类通信,物联网;URLLC,低时延。
一般天线的尺寸为电磁波信号的1/4波长为佳。
调制
从基带数字信号变为射频信号,需要经历两个步骤:
- 基带数字信号转换为基带模拟信号——数字到模拟;
- 模拟基带信号转换为射频信号——低频到高频。
(1)模拟信号调制(低频到高频) 模拟调制分为幅度调至和角度调制
- 调幅:用调制信号去控制高频载波的振幅,使其按调制信号的规律变化,用载波的幅度去承载信息,但载波的频率保持不变。
(接下来的没看懂) p73
天线发射
电磁辐射原理
当导体上通以高频电流时,其周围空间会同时产生电场与磁场。按电磁场在空间的分布特性,可分为近区(电抗近场)、中间区(辐射近场)、远区(辐射远场)。
天线基本原理
没看懂 算了
无线信道与信道衰落
无噪声的完美信道——奈奎斯特带宽
符号速率(码元速率)为1/T(每个码元的传输时长为T)时,进行无码间串扰传输所需最小带宽为1/2T,揭示了带宽的关系。
奈奎斯特速率和奈奎斯特带宽是同一理论的一体两面,奈奎斯特速率指的是在无噪声理想低通信道情况下不发生码间干扰的最大的符号速率,其表达式为:
C=2Hlog2N C为信息传输速率(单位 bit/s),H为理想低通信道的带宽(单位 Hz),N为一个码元对应的离散值个数(编码级数或多相调制的级数)。
奈奎斯特贷款和速度证明了很重要的一点,那就是没有噪声的情况下,数据率的限制仅仅来自信号的带宽。奈奎斯特带宽和速率可以描述为:在无噪声的理想情况下,如果带宽为B,那么可被传输的最大信号速率就是2B;反过来说 信号传输速率为2B,那么频宽B的带宽就完全能够达到此信号的传输速率。
模拟
5 最长回文子串
朴素解法
- 枚举字符串
- 回文串长度是奇数,则依次判断s[i-k]==s[i+k],k=1,2,3...
- 回文串长度是偶数,则依次判断s[i-k]==[i+k-1],k=1,1,3...
public String longestPalindrome(String s){
String ans = "";
for(int i=0;i<s.length();i++){
//回文串为奇数
int l = i-1,r=i+1;
String sub = getString(s,l,r);
if(sub.length()>ans.length()) ans = sub;
//回文串为偶数
l = i-1;
r = i+1-1;
sub = getString(s,l,r);
if(sub.length()>ans.length()) ans = sub;
}
return ans;
}
String getString(String s,int l ,int r){
while(l>=0&&r<s.length()&&s.charAt(l)==s.charAt(r)){
l--;
r++;
}
return s.substring(l+1,r); // l+1 是因为 l--了,对应的范围应该要+1,而r因为api的原因,是取不到的,所以不用处理。
//即 substring为 左闭右开的。
}
动态规划
public String longestPalindrome(String s) {
int len = s.length();
if(len<2) {
return s;
}
int maxLen =1;
int begin = 0;
boolean[][] dp = new boolean[len][len];
//dp[i][j] 表示 s[i:j] 是否是回文串
for(int i=0;i<len;i++) {
dp[i][i] = true; // 单个的 都为 true
}
char[] charArray = s.toCharArray();
//递推开始
//先枚举子串长度
for(int L=2;L<=len;L++) { // 长度
//枚举左边界,左边界的上限可以设置宽松一些
for(int i=0;i<len;i++) {
//由L和i可以确定右边界,即 j-i+1=L 得
int j = L+i-1;
//如果右边界越界,就可以退出当前循环
if(j>=len) break;
if(charArray[i]!=charArray[j]) {
dp[i][j] = false ;
}else {
if(j-i<3) {//1和2 1:表示 偶数状态下,两个字符相等,是回文,2 奇数下,回文。 边界条件的判断
dp[i][j] = true;
}else {
dp[i][j] = dp[i+1][j-1]; //状态转移,往外扩
}
}
//只要 dp[i][L] ==ture 成立,就表示子串s[i,L]是回文,此时记录回文长度和起始位置。
if(dp[i][j]&&j-i+1>maxLen) {
maxLen = j-i+1;
begin = i;
}
}
}
return s.substring(begin, begin + maxLen);
}
模拟
43字符串相乘
- 两个数相乘,其最大长度不会超过n+m,因此创建一个长度为n+m的数组来接收结果。
public String multiply(String n1, String n2) {
int n = n1.length(), m = n2.length();
int[] res = new int[n + m];
for (int i = n - 1; i >= 0; i--) {
for (int j = m - 1; j >= 0; j--) {
int a = n1.charAt(i) - '0';
int b = n2.charAt(j) - '0';
int r = a * b; // 先得到乘法
r += res[i + j + 1]; // i和j都是递减的,+1是对应的二位数的低位。
// 例如 123 和456 若是3和6 那么算出来的i+j是4,实际只有个位,要向下再看一位 即下标为5 而下标5就是最低位了。
res[i + j + 1] = r % 10;
res[i + j] += r / 10;
}
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n + m; i++) {
if (sb.length() == 0 && res[i] == 0) continue;
sb.append(res[i]);
}
return sb.length() == 0 ? "0" : sb.toString();
}
73 矩阵置零
O(1) 的空间解法。
- 使用两个变量(r0&c0),记录[首行&首列]是否该被置零
- [非首行首列位置] 1、将置零信息存储到原矩阵 2、根据置零信息,置零[非首行首列]的位置
- 使用r0&c0 置零[首行&首列]
public void setZeroes(int[][] mat) {
int m = mat.length, n = mat[0].length;
//1 扫描[首行]和[首列] 记录 [首行]和[首列]是否被置零
boolean r0=false,c0=false ;
for(int i=0;i<m;i++) {
if(mat[i][0]==0) {
r0 = true;
break;
}
}
for(int j=0;j<n;j++) {
if(mat[0][j]==0) {
c0 = true;
break;
}
}
//扫描[非首行首列]的位置,如果发现零,将需要置零的信息存储到该行的[最左方]和[最上方]的格子内
for(int i=1;i<m;i++) {
for(int j=1;j<n;j++) {
if(mat[i][j]==0) mat[i][0] = mat[0][j]=0;
}
}
// 根据刚刚记录在[最左方]和[最上方]格子内的置零信息,进行[非首行首列] 置零
for(int j=1;j<n;j++) {
if(mat[0][j]==0) {
for(int i=1;i<m;i++) mat[i][j] = 0;
}
}
for(int i=1;i<m;i++) {
if(mat[i][0]==0) Arrays.fill(mat[i], 0);
}
if(r0) for (int i=0;i<m;i++) mat[i][0]=0;
if(c0) Arrays.fill(mat[0], 0);
}